Compare commits

...
Author SHA1 Message Date
Rob Bygrave f53c56490c Merge branch 'master' into ebean-15x 2024-03-03 20:56:17 +13:00
Rob BygraveandGitHub 559b39eedc Merge pull request #3340 from ebean-orm/revert-3212-15x/remove-future-queries
Revert "[15x] Remove "Future queries" findFutureList, findFutureIds, findFutureCount"
2024-02-27 20:26:41 +13:00
Rob Bygrave 0ebcba17f1 #3340 Changes to support Revert "[15x] Remove "Future queries
The spiQuery.usingFuture() was added after the original removal so adding that.
2024-02-26 22:20:39 +13:00
Rob BygraveandGitHub 71edd33fa3 Revert "[15x] Remove "Future queries" findFutureList, findFutureIds, findFutureCount" 2024-02-26 22:02:28 +13:00
Rob Bygrave 24b99d065a Merge branch 'master' into ebean-15x 2024-02-19 22:43:41 +13:00
robin.bygrave db7fbd5246 Merge branch 'master' into ebean-15x 2023-11-07 15:39:06 +13:00
Rob Bygrave ca97338839 Rebase from master 2023-10-11 22:58:59 +13:00
Rob Bygrave 355144f16d [15x] Update test Document model 2023-10-11 22:55:38 +13:00
Rob Bygrave 7316fb8f1d [15x] Remove Inheritance support 2023-10-11 22:55:36 +13:00
Rob Bygrave 475c30c2a2 [15x] Remove "Future queries" findFutureList, findFutureIds, findFutureCount
Note that findFutureCount still exists as an internal implementation detail
of findPagedList but not exposed via Query API for public use.
2023-10-11 22:54:05 +13:00
Rob Bygrave 5a11dcb2e3 [15x] Remove ElasticSearch support 2023-10-11 22:54:05 +13:00
Rob Bygrave 66d29a7f0c [15x] Remove Draftable support 2023-10-11 22:54:05 +13:00
Rob Bygrave e3af5cdeb4 [15x] Remove Read Auditing feature 2023-10-11 22:54:05 +13:00
Rob Bygrave c4bfa48b59 [15x] Remove Named DTO queries and External Mapping (loading named queries) 2023-10-11 22:54:05 +13:00
Rob Bygrave 8473f9fd39 [15x] Remove Named queries, ANTLR, Query language parser 2023-10-11 22:54:00 +13:00
430 changed files with 584 additions and 25702 deletions
@@ -155,10 +155,4 @@ public abstract class BeanFinder<I,T> {
return db().findNative(type, nativeSql);
}
/**
* Creates a query using the ORM query language.
*/
protected Query<T> query(String ormQuery) {
return db().createQuery(type, ormQuery);
}
}
-52
View File
@@ -741,21 +741,6 @@ public final class DB {
return getDefault().createUpdate(beanType, ormUpdate);
}
/**
* Create a named query.
* <p>
* For RawSql the named query is expected to be in ebean.xml.
*
* @param beanType The type of entity bean
* @param namedQuery The name of the query
* @param <T> The type of entity bean
* @return The query
*/
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
return getDefault().createNamedQuery(beanType, namedQuery);
}
/**
* Create a query for a type of entity bean.
* <p>
@@ -775,43 +760,6 @@ public final class DB {
return getDefault().createQuery(beanType);
}
/**
* Parse the Ebean query language statement returning the query which can then
* be modified (add expressions, change order by clause, change maxRows, change
* fetch and select paths etc).
* <p>
* <h3>Example</h3>
* <pre>{@code
*
* // Find order additionally fetching the customer, details and details.product name.
*
* String eql = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
*
* Query<Order> query = DB.createQuery(Order.class, eql);
* query.setParameter("orderId", 2);
*
* Order order = query.findOne();
*
* // This is the same as:
*
* Order order = DB.find(Order.class)
* .fetch("customer")
* .fetch("details")
* .fetch("detail.product", "name")
* .setId(2)
* .findOne();
*
* }</pre>
*
* @param beanType The type of bean to fetch
* @param eql The Ebean query
* @param <T> The type of the entity bean
* @return The query with expressions defined as per the parsed query statement
*/
public static <T> Query<T> createQuery(Class<T> beanType, String eql) {
return getDefault().createQuery(beanType, eql);
}
/**
* Create a query for a type of entity bean.
* <p>
@@ -242,18 +242,6 @@ public interface Database {
*/
<T> UpdateQuery<T> update(Class<T> beanType);
/**
* Create a named query.
* <p>
* For RawSql the named query is expected to be in ebean.xml.
*
* @param beanType The type of entity bean
* @param namedQuery The name of the query
* @param <T> The type of entity bean
* @return The query
*/
<T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
/**
* Create a query for an entity bean and synonym for {@link #find(Class)}.
*
@@ -261,41 +249,6 @@ public interface Database {
*/
<T> Query<T> createQuery(Class<T> beanType);
/**
* Parse the Ebean query language statement returning the query which can then
* be modified (add expressions, change order by clause, change maxRows, change
* fetch and select paths etc).
* <p>
* <h3>Example</h3>
* <pre>{@code
*
* // Find order additionally fetching the customer, details and details.product name.
*
* String ormQuery = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
*
* Query<Order> query = DB.createQuery(Order.class, ormQuery);
* query.setParameter("orderId", 2);
*
* Order order = query.findOne();
*
* // This is the same as:
*
* Order order = DB.find(Order.class)
* .fetch("customer")
* .fetch("details")
* .fetch("detail.product", "name")
* .setId(2)
* .findOne();
*
* }</pre>
*
* @param beanType The type of bean to fetch
* @param ormQuery The Ebean ORM query
* @param <T> The type of the entity bean
* @return The query with expressions defined as per the parsed query statement
*/
<T> Query<T> createQuery(Class<T> beanType, String ormQuery);
/**
* Create a query for a type of entity bean.
* <p>
@@ -459,18 +412,6 @@ public interface Database {
*/
<T> DtoQuery<T> findDto(Class<T> dtoType, String sql);
/**
* Create a named Query for DTO beans.
* <p>
* DTO beans are just normal bean like classes with public constructor(s) and setters.
* They do not need to be registered with DB before use.
*
* @param dtoType The type of the DTO bean the rows will be mapped into.
* @param namedQuery The name of the query
* @param <T> The type of the DTO bean.
*/
<T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery);
/**
* Look to execute a native sql query that does not return beans but instead
* returns SqlRow or direct access to ResultSet.
@@ -1385,109 +1326,6 @@ public interface Database {
*/
ScriptRunner script();
/**
* Return the Document store.
*/
DocumentStore docStore();
/**
* Publish a single bean given its type and id returning the resulting live bean.
* <p>
* The values are published from the draft to the live bean.
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
* @param id the id of the entity bean
* @param transaction the transaction the publish process should use (can be null)
*/
@Nullable
<T> T publish(Class<T> beanType, Object id, Transaction transaction);
/**
* Publish a single bean given its type and id returning the resulting live bean.
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft to the live bean.
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
* @param id the id of the entity bean
*/
@Nullable
<T> T publish(Class<T> beanType, Object id);
/**
* Publish the beans that match the query returning the resulting published beans.
* <p>
* The values are published from the draft beans to the live beans.
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
* @param transaction the transaction the publish process should use (can be null)
*/
<T> List<T> publish(Query<T> query, Transaction transaction);
/**
* Publish the beans that match the query returning the resulting published beans.
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft beans to the live beans.
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
*/
<T> List<T> publish(Query<T> query);
/**
* Restore the draft bean back to the live state.
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
* @param id the id of the entity bean to restore
* @param transaction the transaction the restore process should use (can be null)
*/
@Nullable
<T> T draftRestore(Class<T> beanType, Object id, Transaction transaction);
/**
* Restore the draft bean back to the live state.
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
* @param id the id of the entity bean to restore
*/
@Nullable
<T> T draftRestore(Class<T> beanType, Object id);
/**
* Restore the draft beans matching the query back to the live state.
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
* @param transaction the transaction the restore process should use (can be null)
*/
<T> List<T> draftRestore(Query<T> query, Transaction transaction);
/**
* Restore the draft beans matching the query back to the live state.
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
*/
<T> List<T> draftRestore(Query<T> query);
/**
* Returns the set of properties/paths that are unknown (do not map to known properties or paths).
* <p>
@@ -13,8 +13,6 @@ import io.ebean.event.*;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import jakarta.persistence.EnumType;
import javax.sql.DataSource;
@@ -691,38 +689,6 @@ public interface DatabaseBuilder {
@Deprecated
DatabaseBuilder setChangeLogAsync(boolean changeLogAsync);
/**
* Set the ReadAuditLogger to use. If not set the default implementation is used
* which logs the read events in JSON format to a standard named SLF4J logger
* (which can be configured in say logback to log to a separate log file).
*/
default DatabaseBuilder readAuditLogger(ReadAuditLogger readAuditLogger) {
return setReadAuditLogger(readAuditLogger);
}
/**
* @deprecated migrate to {@link #readAuditLogger(ReadAuditLogger)}.
*/
@Deprecated
DatabaseBuilder setReadAuditLogger(ReadAuditLogger readAuditLogger);
/**
* Set the ReadAuditPrepare to use.
* <p>
* It is expected that an implementation is used that read user context information
* (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
* to the ReadAuditLogger.
*/
default DatabaseBuilder readAuditPrepare(ReadAuditPrepare readAuditPrepare) {
return setReadAuditPrepare(readAuditPrepare);
}
/**
* @deprecated migrate to {@link #readAuditPrepare(ReadAuditPrepare)}.
*/
@Deprecated
DatabaseBuilder setReadAuditPrepare(ReadAuditPrepare readAuditPrepare);
/**
* Set the configuration for profiling.
*/
@@ -1005,16 +971,6 @@ public interface DatabaseBuilder {
@Deprecated
DatabaseBuilder setAllQuotedIdentifiers(boolean allQuotedIdentifiers);
/**
* Set to true if this Database is Document store only instance (has no JDBC DB).
*/
DatabaseBuilder setDocStoreOnly(boolean docStoreOnly);
/**
* Set the configuration for the ElasticSearch integration.
*/
DatabaseBuilder setDocStoreConfig(DocStoreConfig docStoreConfig);
/**
* Set the constraint naming convention used in DDL generation.
*/
@@ -2448,16 +2404,6 @@ public interface DatabaseBuilder {
*/
boolean isChangeLogAsync();
/**
* Return the ReadAuditLogger to use.
*/
ReadAuditLogger getReadAuditLogger();
/**
* Return the ReadAuditPrepare to use.
*/
ReadAuditPrepare getReadAuditPrepare();
/**
* Return the tenancy catalog provider.
*/
@@ -2596,16 +2542,6 @@ public interface DatabaseBuilder {
*/
boolean isAllQuotedIdentifiers();
/**
* Return true if this Database is a Document store only instance (has no JDBC DB).
*/
boolean isDocStoreOnly();
/**
* Return the configuration for the ElasticSearch integration.
*/
DocStoreConfig getDocStoreConfig();
/**
* Return the constraint naming convention used in DDL generation.
*/
@@ -1,94 +0,0 @@
package io.ebean;
/**
* Bean holding the details to update the document store.
*/
public final class DocStoreQueueEntry {
/**
* Action to either update or delete a document from the index.
*/
public enum Action {
/**
* Action is to update a document in the doc store.
*/
INDEX(1),
/**
* Action is to delete a document from the doc store..
*/
DELETE(2),
/**
* An update is required based on a change to a nested/embedded object at a given path.
*/
NESTED(3);
int value;
Action(int value) {
this.value = value;
}
/**
* Return the value associated with this action type.
*/
public int getValue() {
return value;
}
}
private final Action type;
private final String queueId;
private final String path;
private final Object beanId;
/**
* Construct for an INDEX or DELETE action.
*/
public DocStoreQueueEntry(Action type, String queueId, Object beanId) {
this(type, queueId, null, beanId);
}
/**
* Construct for an NESTED/embedded path invalidation action.
*/
public DocStoreQueueEntry(Action type, String queueId, String path, Object beanId) {
this.type = type;
this.queueId = queueId;
this.path = path;
this.beanId = beanId;
}
/**
* Return the event type.
*/
public Action getType() {
return type;
}
/**
* Return the associate queueId.
*/
public String getQueueId() {
return queueId;
}
/**
* Return the path if this is a nested update.
*/
public String getPath() {
return path;
}
/**
* Return the bean id (which matches the document id).
*/
public Object getBeanId() {
return beanId;
}
}
@@ -1,312 +0,0 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import io.ebean.docstore.DocQueryContext;
import io.ebean.docstore.RawDoc;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Document storage operations.
*/
@NonNullApi
public interface DocumentStore {
/**
* Update the associated document store using the result of the query.
* <p>
* This will execute the query against the database creating a document for each
* bean graph and sending this to the document store.
* </p>
* <p>
* Note that the select and fetch paths of the query is set for you to match the
* document structure needed based on <code>@DocStore</code> and <code>@DocStoreEmbedded</code>
* so what this query requires is the predicates only.
* </p>
* <p>
* This query will be executed using findEach so it is safe to use a query
* that will fetch a lot of beans. The default bulkBatchSize is used.
* </p>
*
* @param query The query that selects object to send to the document store.
*/
<T> void indexByQuery(Query<T> query);
/**
* Update the associated document store index using the result of the query additionally specifying a
* bulkBatchSize to use for sending the messages to ElasticSearch.
*
* @param query The query that selects object to send to the document store.
* @param bulkBatchSize The batch size to use when bulk sending to the document store.
*/
<T> void indexByQuery(Query<T> query, int bulkBatchSize);
/**
* Update the document store for all beans of this type.
* <p>
* This is the same as indexByQuery where the query has no predicates and so fetches all rows.
* </p>
*/
void indexAll(Class<?> beanType);
/**
* Return the bean by fetching it's content from the document store.
* If the document is not found null is returned.
* <p>
* Typically this is called indirectly by findOne() on the query.
* </p>
* <pre>{@code
*
* Customer customer =
* database.find(Customer.class)
* .setUseDocStore(true)
* .setId(42)
* .findOne();
*
* }</pre>
*/
@Nullable
<T> T find(DocQueryContext<T> request);
/**
* Execute the find list query. This request is prepared to execute secondary queries.
* <p>
* Typically this is called indirectly by findList() on the query that has setUseDocStore(true).
* </p>
* <pre>{@code
*
* List<Customer> newCustomers =
* database.find(Customer.class)
* .setUseDocStore(true)
* .where().eq("status, Customer.Status.NEW)
* .findList();
*
* }</pre>
*/
<T> List<T> findList(DocQueryContext<T> request);
/**
* Execute the query against the document store returning the paged list.
* <p>
* The query should have <code>firstRow</code> or <code>maxRows</code> set prior to calling this method.
* </p>
* <p>
* Typically this is called indirectly by findPagedList() on the query that has setUseDocStore(true).
* </p>
* <pre>{@code
*
* PagedList<Customer> newCustomers =
* database.find(Customer.class)
* .setUseDocStore(true)
* .where().eq("status, Customer.Status.NEW)
* .setMaxRows(50)
* .findPagedList();
*
* }</pre>
*/
<T> PagedList<T> findPagedList(DocQueryContext<T> request);
/**
* Execute the query against the document store with the expectation of a large set of results
* that are processed in a scrolling resultSet fashion.
* <p>
* For example, with the ElasticSearch doc store this uses SCROLL.
* </p>
* <p>
* Typically this is called indirectly by findEach() on the query that has setUseDocStore(true).
* </p>
* <pre>{@code
*
* database.find(Order.class)
* .setUseDocStore(true)
* .where()... // perhaps add predicates
* .findEach((Order order) -> {
* // process the bean ...
* });
*
* }</pre>
*/
<T> void findEach(DocQueryContext<T> query, Consumer<T> consumer);
/**
* Execute the query against the document store with the expectation of a large set of results
* that are processed in a scrolling resultSet fashion.
* <p>
* Unlike findEach() this provides the opportunity to stop iterating through the large query.
* </p>
* <p>
* For example, with the ElasticSearch doc store this uses SCROLL.
* </p>
* <p>
* Typically this is called indirectly by findEachWhile() on the query that has setUseDocStore(true).
* </p>
* <pre>{@code
*
* database.find(Order.class)
* .setUseDocStore(true)
* .where()... // perhaps add predicates
* .findEachWhile(new Predicate<Order>() {
* @Override
* public void accept(Order bean) {
* // process the bean
*
* // return true to continue, false to stop
* // boolean shouldContinue = ...
* return shouldContinue;
* }
* });
*
* }</pre>
*/
<T> void findEachWhile(DocQueryContext<T> query, Predicate<T> consumer);
/**
* Find each processing raw documents.
*
* @param indexNameType The full index name and type
* @param rawQuery The query to execute
* @param consumer Consumer to process each document
*/
void findEach(String indexNameType, String rawQuery, Consumer<RawDoc> consumer);
/**
* Find each processing raw documents stopping when the predicate returns false.
*
* @param indexNameType The full index name and type
* @param rawQuery The query to execute
* @param consumer Consumer to process each document until false is returned
*/
void findEachWhile(String indexNameType, String rawQuery, Predicate<RawDoc> consumer);
/**
* Process the queue entries sending updates to the document store or queuing them for later processing.
*/
long process(List<DocStoreQueueEntry> queueEntries) throws IOException;
/**
* Drop the index from the document store (similar to DDL drop table).
* <pre>{@code
*
* DocumentStore documentStore = database.docStore();
*
* documentStore.dropIndex("product_copy");
*
* }</pre>
*/
void dropIndex(String indexName);
/**
* Create an index given a mapping file as a resource in the classPath (similar to DDL create table).
* <pre>{@code
*
* DocumentStore documentStore = database.docStore();
*
* // uses product_copy.mapping.json resource
* // ... to define mappings for the index
*
* documentStore.createIndex("product_copy", null);
*
* }</pre>
*
* @param indexName the name of the new index
* @param alias the alias of the index
*/
void createIndex(String indexName, String alias);
/**
* Modify the settings on an index.
* <p>
* For example, this can be used be used to set elasticSearch refresh_interval
* on an index before a bulk update.
* </p>
* <pre>{@code
*
* // refresh_interval -1 ... disable refresh while bulk loading
*
* Map<String,Object> settings = new LinkedHashMap<>();
* settings.put("refresh_interval", "-1");
*
* documentStore.indexSettings("product", settings);
*
* }</pre>
* <pre>{@code
*
* // refresh_interval 1s ... restore after bulk loading
*
* Map<String,Object> settings = new LinkedHashMap<>();
* settings.put("refresh_interval", "1s");
*
* documentStore.indexSettings("product", settings);
*
* }</pre>
*
* @param indexName the name of the index to update settings on
* @param settings the settings to set on the index
*/
void indexSettings(String indexName, Map<String, Object> settings);
/**
* Copy the index to a new index.
* <p>
* This copy process does not use the database but instead will copy from the source index to a destination index.
* </p>
* <pre>{@code
*
* long copyCount = documentStore.copyIndex(Product.class, "product_copy");
*
* }</pre>
*
* @param beanType The bean type of the source index
* @param newIndex The name of the index to copy to
* @return the number of documents copied to the new index
*/
long copyIndex(Class<?> beanType, String newIndex);
/**
* Copy entries from an index to a new index but limiting to documents that have been
* modified since the sinceEpochMillis time.
* <p>
* To support this the document needs to have a <code>@WhenModified</code> property.
* </p>
* <pre>{@code
*
* long copyCount = documentStore.copyIndex(Product.class, "product_copy", sinceMillis);
*
* }</pre>
*
* @param beanType The bean type of the source index
* @param newIndex The name of the index to copy to
* @return the number of documents copied to the new index
*/
long copyIndex(Class<?> beanType, String newIndex, long sinceEpochMillis);
/**
* Copy from a source index to a new index taking only the documents
* matching the given query.
* <pre>{@code
*
* // predicates to select the source documents to copy
* Query<Product> query = database.find(Product.class)
* .where()
* .ge("whenModified", new Timestamp(since))
* .ge("name", "A")
* .lt("name", "D")
* .query();
*
* // copy from the source index to "product_copy" index
* long copyCount = documentStore.copyIndex(query, "product_copy", 1000);
*
* }</pre>
*
* @param query The query to select the source documents to copy
* @param newIndex The target index to copy the documents to
* @param bulkBatchSize The ElasticSearch bulk batch size, if 0 uses the default.
* @return The number of documents copied to the new index.
*/
long copyIndex(Query<?> query, String newIndex, int bulkBatchSize);
}
@@ -1,7 +1,5 @@
package io.ebean;
import io.ebean.search.*;
import java.util.Collection;
import java.util.Map;
@@ -625,31 +623,6 @@ public interface ExpressionFactory {
*/
Expression raw(String raw);
/**
* Create a Text Match expression (currently doc store/Elastic only).
*/
Expression textMatch(String propertyName, String search, Match options);
/**
* Create a Text Multi match expression (currently doc store/Elastic only).
*/
Expression textMultiMatch(String query, MultiMatch options);
/**
* Create a text simple query expression (currently doc store/Elastic only).
*/
Expression textSimple(String search, TextSimple options);
/**
* Create a text query string expression (currently doc store/Elastic only).
*/
Expression textQueryString(String search, TextQueryString options);
/**
* Create a text common terms expression (currently doc store/Elastic only).
*/
Expression textCommonTerms(String search, TextCommonTerms options);
/**
* And - join two expressions with a logical and.
*/
@@ -693,12 +666,4 @@ public interface ExpressionFactory {
*/
<T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent);
/**
* Add the expressions to the given expression list.
*
* @param where The expression list to add the expressions to
* @param expressions The expressions that are parsed
* @param params Bind parameters to match ? or ?1 bind positions.
*/
<T> void where(ExpressionList<T> where, String expressions, Object[] params);
}
@@ -2,7 +2,6 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import io.ebean.search.*;
import jakarta.persistence.NonUniqueResultException;
import java.sql.Connection;
@@ -106,11 +105,6 @@ public interface ExpressionList<T> {
*/
Query<T> asOf(Timestamp asOf);
/**
* Execute the query against the draft set of tables.
*/
Query<T> asDraft();
/**
* Convert the query to a DTO bean query.
* <p>
@@ -507,28 +501,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> filterMany(String manyProperty);
/**
* @deprecated for removal - migrate to {@link #filterManyRaw(String, String, Object...)}.
* <p>
* Add filter expressions to the many property.
*
* <pre>{@code
*
* DB.find(Customer.class)
* .where()
* .eq("name", "Rob")
* .filterMany("orders", "status = ?", Status.NEW)
* .findList();
*
* }</pre>
*
* @param manyProperty The many property
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
@Deprecated(forRemoval = true)
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Add filter expressions for the many path. The expressions can include SQL functions if
* desired and the property names are translated to column names.
@@ -580,19 +552,6 @@ public interface ExpressionList<T> {
*/
Query<T> setDistinct(boolean distinct);
/**
* Set the index(es) to search for a document store which uses partitions.
* <p>
* For example, when executing a query against ElasticSearch with daily indexes we can
* explicitly specify the indexes to search against.
* </p>
*
* @param indexName The index or indexes to search against
* @return This query
* @see Query#setDocIndexName(String)
*/
Query<T> setDocIndexName(String indexName);
/**
* Set the first row to fetch.
*
@@ -676,14 +635,6 @@ public interface ExpressionList<T> {
return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
}
/**
* Set to true if this query should execute against the doc store.
* <p>
* When setting this you may also consider disabling lazy loading.
* </p>
*/
Query<T> setUseDocStore(boolean useDocsStore);
/**
* Set true if you want to disable lazy loading.
* <p>
@@ -692,16 +643,6 @@ public interface ExpressionList<T> {
*/
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
/**
* Disable read auditing for this query.
* <p>
* This is intended to be used when the query is not a user initiated query and instead
* part of the internal processing in an application to load a cache or document store etc.
* In these cases we don't want the query to be part of read auditing.
* </p>
*/
Query<T> setDisableReadAuditing();
/**
* Set a label on the query (to help identify query execution statistics).
*/
@@ -721,14 +662,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> where();
/**
* Add the expressions to this expression list.
*
* @param expressions The expressions that are parsed and added to this expression list
* @param params Bind parameters to match ? or ?1 bind positions.
*/
ExpressionList<T> where(String expressions, Object... params);
/**
* Path exists - for the given path in a JSON document.
* <pre>{@code
@@ -1623,47 +1556,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
/**
* Add a match expression.
*
* @param propertyName The property name for the match
* @param search The search value
*/
ExpressionList<T> match(String propertyName, String search);
/**
* Add a match expression with options.
*
* @param propertyName The property name for the match
* @param search The search value
*/
ExpressionList<T> match(String propertyName, String search, Match options);
/**
* Add a multi-match expression.
*/
ExpressionList<T> multiMatch(String search, String... properties);
/**
* Add a multi-match expression using options.
*/
ExpressionList<T> multiMatch(String search, MultiMatch options);
/**
* Add a simple query string expression.
*/
ExpressionList<T> textSimple(String search, TextSimple options);
/**
* Add a query string expression.
*/
ExpressionList<T> textQueryString(String search, TextQueryString options);
/**
* Add common terms expression.
*/
ExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
/**
* And - join two expressions with a logical and.
*/
@@ -1806,42 +1698,6 @@ public interface ExpressionList<T> {
*/
Junction<T> disjunction();
/**
* Start a list of expressions that will be joined by MUST.
* <p>
* This automatically makes the query a useDocStore(true) query that
* will execute against the document store (ElasticSearch etc).
* </p>
* <p>
* This is logically similar to and().
* </p>
*/
Junction<T> must();
/**
* Start a list of expressions that will be joined by SHOULD.
* <p>
* This automatically makes the query a useDocStore(true) query that
* will execute against the document store (ElasticSearch etc).
* </p>
* <p>
* This is logically similar to or().
* </p>
*/
Junction<T> should();
/**
* Start a list of expressions that will be joined by MUST NOT.
* <p>
* This automatically makes the query a useDocStore(true) query that
* will execute against the document store (ElasticSearch etc).
* </p>
* <p>
* This is logically similar to not().
* </p>
*/
Junction<T> mustNot();
/**
* End a junction returning the parent expression list.
* <p>
@@ -213,11 +213,4 @@ public class Finder<I, T> {
return db().findNative(type, nativeSql);
}
/**
* Creates a query using the ORM query language.
*/
public Query<T> query(String ormQuery) {
return db().createQuery(type, ormQuery);
}
}
-103
View File
@@ -250,11 +250,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> asOf(Timestamp asOf);
/**
* Execute the query against the draft set of tables.
*/
Query<T> asDraft();
/**
* Convert the query to a DTO bean query.
* <p>
@@ -321,43 +316,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setPersistenceContextScope(PersistenceContextScope scope);
/**
* Set the index(es) to search for a document store which uses partitions.
* <p>
* For example, when executing a query against ElasticSearch with daily indexes we can
* explicitly specify the indexes to search against.
* </p>
* <pre>{@code
*
* // explicitly specify the indexes to search
* query.setDocIndexName("logstash-2016.11.5,logstash-2016.11.6")
*
* // search today's index
* query.setDocIndexName("$today")
*
* // search the last 3 days
* query.setDocIndexName("$last-3")
*
* }</pre>
* <p>
* If the indexName is specified with ${daily} e.g. "logstash-${daily}" ... then we can use
* $today and $last-x as the search docIndexName like the examples below.
* </p>
* <pre>{@code
*
* // search today's index
* query.setDocIndexName("$today")
*
* // search the last 3 days
* query.setDocIndexName("$last-3")
*
* }</pre>
*
* @param indexName The index or indexes to search against
* @return This query
*/
Query<T> setDocIndexName(String indexName);
/**
* Return the ExpressionFactory used by this query.
*/
@@ -424,16 +382,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setIncludeSoftDeletes();
/**
* Disable read auditing for this query.
* <p>
* This is intended to be used when the query is not a user initiated query and instead
* part of the internal processing in an application to load a cache or document store etc.
* In these cases we don't want the query to be part of read auditing.
* </p>
*/
Query<T> setDisableReadAuditing();
/**
* Specify the properties to fetch on the root level entity bean in comma delimited format.
* <p>
@@ -1322,27 +1270,6 @@ public interface Query<T> extends CancelableQuery {
*/
ExpressionList<T> where();
/**
* Add Full text search expressions for Document store queries.
* <p>
* This is currently ElasticSearch only and provides the full text
* expressions such as Match and Multi-Match.
* </p>
* <p>
* This automatically makes this query a "Doc Store" query and will execute
* against the document store (ElasticSearch).
* </p>
* <p>
* Expressions added here are added to the "query" section of an ElasticSearch
* query rather than the "filter" section.
* </p>
* <p>
* Expressions added to the where() are added to the "filter" section of an
* ElasticSearch query.
* </p>
*/
ExpressionList<T> text();
/**
* This applies a filter on the 'many' property list rather than the root
* level objects.
@@ -1601,14 +1528,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setLabel(String label);
/**
* Set to true if this query should execute against the doc store.
* <p>
* When setting this you may also consider disabling lazy loading.
* </p>
*/
Query<T> setUseDocStore(boolean useDocStore);
/**
* When set to true when you want the returned beans to be read only.
*/
@@ -1743,28 +1662,6 @@ public interface Query<T> extends CancelableQuery {
*/
Class<T> getBeanType();
/**
* Restrict the query to only return subtypes of the given inherit type.
*
* <pre>{@code
*
* List<Animal> animals =
* new QAnimal()
* .name.startsWith("Fluffy")
* .setInheritType(Cat.class)
* .findList();
*
* }</pre>
*
* @param type An inheritance subtype of the
*/
Query<T> setInheritType(Class<? extends T> type);
/**
* Returns the inherit type. This is normally the same as getBeanType() returns as long as no other type is set.
*/
Class<? extends T> getInheritType();
/**
* Return the type of query being executed.
*/
@@ -1,9 +1,7 @@
package io.ebean;
import io.ebean.annotation.DocStoreMode;
import io.ebean.annotation.PersistBatch;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DocStoreConfig;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
@@ -211,29 +209,6 @@ public interface Transaction extends AutoCloseable {
*/
boolean isActive();
/**
* Set the behavior for document store updates on this transaction.
* <p>
* For example, set the mode to DocStoreEvent.IGNORE for this transaction and
* then any changes via this transaction are not sent to the doc store. This
* would be used when doing large bulk inserts into the database and we want
* to control how that is sent to the document store.
* </p>
*/
void setDocStoreMode(DocStoreMode mode);
/**
* Set the batch size to use for sending messages to the document store.
* <p>
* You might set this if you know the changes in this transaction result in especially large or
* especially small payloads and want to adjust the batch size to match.
* </p>
* <p>
* Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
* </p>
*/
void setDocStoreBatchSize(int batchSize);
/**
* Explicitly turn off or on the cascading nature of save() and delete(). This
* gives the developer exact control over what beans are saved and deleted
@@ -16,8 +16,6 @@ import io.ebean.event.*;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetricNamingMatch;
import io.ebean.util.StringHelper;
import jakarta.persistence.EnumType;
@@ -137,16 +135,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
*/
private List<String> packages = new ArrayList<>();
/**
* Configuration for the ElasticSearch integration.
*/
private DocStoreConfig docStoreConfig = new DocStoreConfig();
/**
* Set to true when the Database only uses Document store.
*/
private boolean docStoreOnly;
/**
* This is used to populate @WhoCreated, @WhoModified and
* support other audit features (who executed a query etc).
@@ -421,8 +409,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
private ChangeLogListener changeLogListener;
private ChangeLogRegister changeLogRegister;
private boolean changeLogAsync = true;
private ReadAuditLogger readAuditLogger;
private ReadAuditPrepare readAuditPrepare;
private EncryptKeyManager encryptKeyManager;
private EncryptDeployManager encryptDeployManager;
private Encryptor encryptor;
@@ -996,28 +982,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
return this;
}
@Override
public ReadAuditLogger getReadAuditLogger() {
return readAuditLogger;
}
@Override
public DatabaseConfig setReadAuditLogger(ReadAuditLogger readAuditLogger) {
this.readAuditLogger = readAuditLogger;
return this;
}
@Override
public ReadAuditPrepare getReadAuditPrepare() {
return readAuditPrepare;
}
@Override
public DatabaseConfig setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
this.readAuditPrepare = readAuditPrepare;
return this;
}
@Override
public ProfilingConfig getProfilingConfig() {
return profilingConfig;
@@ -1292,28 +1256,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
}
}
@Override
public boolean isDocStoreOnly() {
return docStoreOnly;
}
@Override
public DatabaseConfig setDocStoreOnly(boolean docStoreOnly) {
this.docStoreOnly = docStoreOnly;
return this;
}
@Override
public DocStoreConfig getDocStoreConfig() {
return docStoreConfig;
}
@Override
public DatabaseConfig setDocStoreConfig(DocStoreConfig docStoreConfig) {
this.docStoreConfig = docStoreConfig;
return this;
}
@Override
public DbConstraintNaming getConstraintNaming() {
return platformConfig.getConstraintNaming();
@@ -2086,13 +2028,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
}
/**
* This is broken out to allow overridden behaviour.
*/
protected void loadDocStoreSettings(PropertiesWrapper p) {
docStoreConfig.loadSettings(p);
}
/**
* This is broken out to allow overridden behaviour.
*/
@@ -2124,11 +2059,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
}
loadDataSourceSettings(p);
if (docStoreConfig == null) {
docStoreConfig = new DocStoreConfig();
}
loadDocStoreSettings(p);
defaultServer = p.getBoolean("defaultServer", defaultServer);
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
@@ -2144,7 +2074,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
@@ -1,320 +0,0 @@
package io.ebean.config;
import io.ebean.Transaction;
import io.ebean.annotation.DocStoreMode;
/**
* Configuration for the Document store integration (e.g. ElasticSearch).
*/
public class DocStoreConfig {
/**
* True when the Document store integration is active/on.
*/
protected boolean active;
/**
* Set to true means Ebean will generate mapping files on startup.
*/
protected boolean generateMapping;
/**
* When true the Document store should drop and re-create document indexes.
*/
protected boolean dropCreate;
/**
* When true the Document store should create any document indexes that don't already exist.
*/
protected boolean create;
/**
* The URL of the Document store. For example: http://localhost:9200.
*/
protected String url;
/**
* Credential that be used for authentication to document store.
*/
protected String username;
/**
* Password credential that be used for authentication to document store.
*/
protected String password;
/**
* Set to true such that the client allows connections to invalid/self signed SSL certificates.
*/
protected boolean allowAllCertificates;
/**
* The default mode used by indexes.
*/
protected DocStoreMode persist = DocStoreMode.UPDATE;
/**
* The default batch size to use for the Bulk API calls.
*/
protected int bulkBatchSize = 1000;
/**
* Resource path for the Document store mapping files.
*/
protected String mappingPath;
/**
* Suffix used for mapping files.
*/
protected String mappingSuffix;
/**
* Location of resources that mapping files are generated into.
*/
protected String pathToResources = "src/main/resources";
/**
* Return true if the Document store (ElasticSearch) integration is active.
*/
public boolean isActive() {
String systemValue = System.getProperty("ebean.docstore.active");
if (systemValue != null) {
return Boolean.parseBoolean(systemValue);
}
return active;
}
/**
* Set to true to make the Document store (ElasticSearch) integration active.
*/
public void setActive(boolean active) {
this.active = active;
}
/**
* Return the URL to the Document store.
*/
public String getUrl() {
String systemValue = System.getProperty("ebean.docstore.url");
if (systemValue != null) {
return systemValue;
}
return url;
}
/**
* Return the user credential for connecting to the document store.
*/
public String getUsername() {
return username;
}
/**
* Set the user credential for connecting to the document store.
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Return the password credential for connecting to the document store.
*/
public String getPassword() {
return password;
}
/**
* Set the password credential for connecting to the document store.
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Set the URL to the Document store.
* <p>
* For a local ElasticSearch server this would be: http://localhost:9200
*/
public void setUrl(String url) {
this.url = url;
}
/**
* Return true if Ebean should generate mapping files on server startup.
*/
public boolean isGenerateMapping() {
String systemValue = System.getProperty("ebean.docstore.generateMapping");
if (systemValue != null) {
return Boolean.parseBoolean(systemValue);
}
return generateMapping;
}
/**
* Set to true if Ebean should generate mapping files on server startup.
*/
public void setGenerateMapping(boolean generateMapping) {
this.generateMapping = generateMapping;
}
/**
* Return true if the document store should recreate mapped indexes.
*/
public boolean isDropCreate() {
String systemValue = System.getProperty("ebean.docstore.dropCreate");
if (systemValue != null) {
return Boolean.parseBoolean(systemValue);
}
return dropCreate;
}
/**
* Set to true if the document store should recreate mapped indexes.
*/
public void setDropCreate(boolean dropCreate) {
this.dropCreate = dropCreate;
}
/**
* Create true if the document store should create mapped indexes that don't yet exist.
* This is only used if dropCreate is false.
*/
public boolean isCreate() {
String systemValue = System.getProperty("ebean.docstore.create");
if (systemValue != null) {
return Boolean.parseBoolean(systemValue);
}
return create;
}
/**
* Set to true if the document store should create mapped indexes that don't yet exist.
* This is only used if dropCreate is false.
*/
public void setCreate(boolean create) {
this.create = create;
}
/**
* Return true if the client allows connections to invalid/self signed SSL certificates.
*/
public boolean isAllowAllCertificates() {
return allowAllCertificates;
}
/**
* Set to true such that the client allows connections to invalid/self signed SSL certificates.
*/
public void setAllowAllCertificates(boolean allowAllCertificates) {
this.allowAllCertificates = allowAllCertificates;
}
/**
* Return the default batch size to use for calls to the Bulk API.
*/
public int getBulkBatchSize() {
return bulkBatchSize;
}
/**
* Set the default batch size to use for calls to the Bulk API.
* <p>
* The batch size can be set on a transaction via {@link Transaction#setDocStoreBatchSize(int)}.
* </p>
*/
public void setBulkBatchSize(int bulkBatchSize) {
this.bulkBatchSize = bulkBatchSize;
}
/**
* Return the mapping path.
*/
public String getMappingPath() {
return mappingPath;
}
/**
* Set the mapping path.
*/
public void setMappingPath(String mappingPath) {
this.mappingPath = mappingPath;
}
/**
* Return the mapping suffix.
*/
public String getMappingSuffix() {
return mappingSuffix;
}
/**
* Set the mapping suffix.
*/
public void setMappingSuffix(String mappingSuffix) {
this.mappingSuffix = mappingSuffix;
}
/**
* Return the relative file system path to resources when generating mapping files.
*/
public String getPathToResources() {
return pathToResources;
}
/**
* Set the relative file system path to resources when generating mapping files.
*/
public void setPathToResources(String pathToResources) {
this.pathToResources = pathToResources;
}
/**
* Return the default behavior for when Insert, Update and Delete events occur on beans that have an associated
* Document store.
*/
public DocStoreMode getPersist() {
return persist;
}
/**
* Set the default behavior for when Insert, Update and Delete events occur on beans that have an associated
* Document store.
* <ul>
* <li>DocStoreEvent.UPDATE - build and send message to Bulk API</li>
* <li>DocStoreEvent.QUEUE - add an entry with the index type and id only into a queue for later processing</li>
* <li>DocStoreEvent.IGNORE - ignore. Most likely used when some scheduled batch job handles updating the index</li>
* </ul>
* <p>
* You might choose to use QUEUE if that particular index data is updating very frequently or the cost of indexing
* is expensive. Setting it to QUEUE can mean many changes can be batched together potentially coalescing multiple
* updates for an index entry into a single update.
* </p>
* <p>
* You might choose to use IGNORE when you have your own external process for updating the indexes. In this case
* you don't want Ebean to do anything when the data changes.
* </p>
*/
public void setPersist(DocStoreMode persist) {
this.persist = persist;
}
/**
* Load settings specified in properties files.
*/
public void loadSettings(PropertiesWrapper properties) {
active = properties.getBoolean("docstore.active", active);
url = properties.get("docstore.url", url);
username = properties.get("docstore.username", url);
password = properties.get("docstore.password", url);
persist = properties.getEnum(DocStoreMode.class, "docstore.persist", persist);
bulkBatchSize = properties.getInt("docstore.bulkBatchSize", bulkBatchSize);
generateMapping = properties.getBoolean("docstore.generateMapping", generateMapping);
dropCreate = properties.getBoolean("docstore.dropCreate", dropCreate);
create = properties.getBoolean("docstore.create", create);
allowAllCertificates = properties.getBoolean("docstore.allowAllCertificates", allowAllCertificates);
mappingPath = properties.get("docstore.mappingPath", mappingPath);
mappingSuffix = properties.get("docstore.mappingSuffix", mappingSuffix);
pathToResources = properties.get("docstore.pathToResources", pathToResources);
}
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document Mapping for a bean marker interface.
*/
public interface DocMapping {
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document query request context marker interface.
*/
public interface DocQueryContext<T> {
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document update context marker interface.
*/
public interface DocUpdateContext {
}
@@ -1,102 +0,0 @@
package io.ebean.docstore;
import java.util.Map;
/**
* Raw document.
*/
public class RawDoc {
private Map<String, Object> source;
private String id;
private double score;
private String index;
private String type;
/**
* Construct the document with all the meta data.
*/
public RawDoc(Map<String, Object> source, String id, double score, String index, String type) {
this.source = source;
this.id = id;
this.score = score;
this.index = index;
this.type = type;
}
/**
* Construct empty (typically for JSON marshalling).
*/
public RawDoc() {
}
/**
* Return the source document as a Map.
*/
public Map<String, Object> getSource() {
return source;
}
/**
* Return the Id value.
*/
public String getId() {
return id;
}
/**
* Return the score.
*/
public double getScore() {
return score;
}
/**
* Return the index name.
*/
public String getIndex() {
return index;
}
/**
* Return the index type.
*/
public String getType() {
return type;
}
/**
* Set the source document.
*/
public void setSource(Map<String, Object> source) {
this.source = source;
}
/**
* Set the id value.
*/
public void setId(String id) {
this.id = id;
}
/**
* Set the score.
*/
public void setScore(double score) {
this.score = score;
}
/**
* Set the index name.
*/
public void setIndex(String index) {
this.index = index;
}
/**
* Set the index type.
*/
public void setType(String type) {
this.type = type;
}
}
@@ -1,37 +0,0 @@
package io.ebean.event.readaudit;
/**
* Log that the query was executed
*/
public interface ReadAuditLogger {
/**
* Called when a new query plan is created.
* <p>
* The query plan has the full sql and logging the query plan separately means that each of
* the bean and many read events can log the query plan key and not the full sql (reducing the
* bulk size of the read audit logs).
* </p>
*/
void queryPlan(ReadAuditQueryPlan queryPlan);
/**
* Audit a find bean query that returned a bean.
* <p>
* Finds that did not return a bean are excluded.
* </p>
*/
void auditBean(ReadEvent readBean);
/**
* Audit a find many query that returned some beans.
* <p>
* Finds that did not return any beans are excluded.
* </p>
* <p>
* For large queries executed via findEach() etc the ids are collected in batches
* and logged. Hence the ids list has a maximum size of the batch size.
* </p>
*/
void auditMany(ReadEvent readMany);
}
@@ -1,23 +0,0 @@
package io.ebean.event.readaudit;
/**
* Set user context information into the read event prior to it being logged.
*/
public interface ReadAuditPrepare {
/**
* Prepare the read event by setting any user context information into the read event such as the
* application user id and ip address.
* <p>
* This method is called prior to the read event being sent to the ReadAuditLogger.
* </p>
* <p>
* Note that for findFutureList() queries prepare() is called early in the foreground thread
* prior to the query executing and at that point the ReadEvent bean only has the bean type
* and no other details (which are populated later when the query is executed in the background
* thread).
* </p>
*/
void prepare(ReadEvent readEvent);
}
@@ -1,97 +0,0 @@
package io.ebean.event.readaudit;
/**
* A SQL query and associated keys.
* <p>
* This is logged as a separate event so that the
* </p>
*/
public class ReadAuditQueryPlan {
String beanType;
String queryKey;
String sql;
/**
* Construct given the beanType, queryKey and sql.
*/
public ReadAuditQueryPlan(String beanType, String queryKey, String sql) {
this.beanType = beanType;
this.queryKey = queryKey;
this.sql = sql;
}
/**
* Construct for JSON tools.
*/
public ReadAuditQueryPlan() {
}
@Override
public String toString() {
return "beanType:" + beanType + " queryKey:" + queryKey + " sql:" + sql;
}
/**
* Return the bean type.
*/
public String getBeanType() {
return beanType;
}
/**
* Set the bean type.
*/
public void setBeanType(String beanType) {
this.beanType = beanType;
}
/**
* Return the query key (relative to the bean type).
*/
public String getQueryKey() {
return queryKey;
}
/**
* Set the query key.
*/
public void setQueryKey(String queryKey) {
this.queryKey = queryKey;
}
/**
* Return the sql statement.
*/
public String getSql() {
return sql;
}
/**
* Set the sql statement.
*/
public void setSql(String sql) {
this.sql = sql;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ReadAuditQueryPlan that = (ReadAuditQueryPlan) o;
if (!beanType.equals(that.beanType)) return false;
if (!queryKey.equals(that.queryKey)) return false;
return sql.equals(that.sql);
}
@Override
public int hashCode() {
int result = beanType.hashCode();
result = 92821 * result + queryKey.hashCode();
result = 92821 * result + sql.hashCode();
return result;
}
}
@@ -1,261 +0,0 @@
package io.ebean.event.readaudit;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Read event sent to the ReadEventLogger.
* <p>
* This is a flattened in that it contains either a read bean or list of beans. It is flattened
* in this way to simplify logging and processing and simply means that it either contains an
* id or a list of ids.
* </p>
*/
public class ReadEvent {
/**
* User defined 'source' such as the application name.
*/
protected String source;
/**
* Application user id expected to be optionally populated by ChangeLogPrepare.
*/
protected String userId;
/**
* Application user ip address expected to be optionally populated by ChangeLogPrepare.
*/
protected String userIpAddress;
/**
* Arbitrary user context information expected to be optionally populated by ChangeLogPrepare.
*/
protected Map<String, String> userContext;
/**
* The time the bean change was created.
*/
protected long eventTime;
/**
* The type of the bean(s) read.
*/
protected String beanType;
/**
* The query key (relative to the bean type).
*/
protected String queryKey;
/**
* The bind log when the query was executed.
*/
protected String bindLog;
/**
* The id of the bean read.
*/
protected Object id;
/**
* The ids of the beans read.
*/
protected List<Object> ids;
/**
* Common constructor for single bean and multi-bean read events.
*/
protected ReadEvent(String beanType, String queryKey, String bindLog) {
this.beanType = beanType;
this.queryKey = queryKey;
this.bindLog = bindLog;
this.eventTime = System.currentTimeMillis();
}
/**
* Construct for a single bean read.
*/
public ReadEvent(String beanType, String queryKey, String bindLog, Object id) {
this(beanType, queryKey, bindLog);
this.id = id;
}
/**
* Construct for many beans read.
*/
public ReadEvent(String beanType, String queryKey, String bindLog, List<Object> ids) {
this(beanType, queryKey, bindLog);
this.ids = ids;
}
/**
* Construct for many future list query.
*/
public ReadEvent(String beanType) {
this.beanType = beanType;
this.eventTime = System.currentTimeMillis();
}
/**
* Constructor for JSON tools.
*/
public ReadEvent() {
}
/**
* Return a code that identifies the source of the change (like the name of the application).
*/
public String getSource() {
return source;
}
/**
* Set the source of the change (like the name of the application).
*/
public void setSource(String source) {
this.source = source;
}
/**
* Return the application user Id.
*/
public String getUserId() {
return userId;
}
/**
* Set the application user Id.
* <p>
* This can be set by the ChangeLogListener in the prepare() method which is called
* in the foreground thread.
* </p>
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* Return the application users ip address.
*/
public String getUserIpAddress() {
return userIpAddress;
}
/**
* Set the application users ip address.
* <p>
* This can be set by the ChangeLogListener in the prepare() method which is called
* in the foreground thread.
* </p>
*/
public void setUserIpAddress(String userIpAddress) {
this.userIpAddress = userIpAddress;
}
/**
* Return a user context value - anything you set yourself in ChangeLogListener prepare().
*/
public Map<String, String> getUserContext() {
if (userContext == null) {
userContext = new LinkedHashMap<>();
}
return userContext;
}
/**
* Set a user context value (anything you like).
* <p>
* This can be set by the ChangeLogListener in the prepare() method which is called
* in the foreground thread.
* </p>
*/
public void setUserContext(Map<String, String> userContext) {
this.userContext = userContext;
}
/**
* Return the type of bean read.
*/
public String getBeanType() {
return beanType;
}
/**
* Set the type of bean read.
*/
public void setBeanType(String beanType) {
this.beanType = beanType;
}
/**
* Return the query key (relative to the bean type).
*/
public String getQueryKey() {
return queryKey;
}
/**
* Set the query key (relative to the bean type).
*/
public void setQueryKey(String queryKey) {
this.queryKey = queryKey;
}
/**
* Return the bind log used when executing the query.
*/
public String getBindLog() {
return bindLog;
}
/**
* Set the bind log used when executing the query.
*/
public void setBindLog(String bindLog) {
this.bindLog = bindLog;
}
/**
* Return the event date time.
*/
public long getEventTime() {
return eventTime;
}
/**
* Set the event date time.
*/
public void setEventTime(long eventTime) {
this.eventTime = eventTime;
}
/**
* Return the id of the bean read.
*/
public Object getId() {
return id;
}
/**
* Set the id of the bean read.
*/
public void setId(Object id) {
this.id = id;
}
/**
* Return the ids of the beans read.
*/
public List<Object> getIds() {
return ids;
}
/**
* Set the ids of the beans read.
*/
public void setIds(List<Object> ids) {
this.ids = ids;
}
}
@@ -1,8 +0,0 @@
/**
* Provides Auditing of read events including queries and L2 cache.
* <p>
* Provides a built support for supplied an audit of all the 'read events' for beans annotated
* with <code>@ReadAudit</code>
* </p>
*/
package io.ebean.event.readaudit;
@@ -1,72 +0,0 @@
package io.ebean.plugin;
import io.ebean.FetchPath;
import io.ebean.Query;
import io.ebean.docstore.DocUpdateContext;
import java.io.IOException;
/**
* Doc store functions for a specific entity bean type.
*
* @param <T> The type of entity bean
*/
public interface BeanDocType<T> {
/**
* Return the doc store index type for this bean type.
*/
String indexType();
/**
* Return the doc store index name for this bean type.
*/
String indexName();
/**
* Apply the appropriate fetch path to the query such that the query returns beans matching
* the document store structure with the expected embedded properties.
*/
void applyPath(Query<T> spiQuery);
/**
* Return the FetchPath for the embedded document.
*/
FetchPath embedded(String path);
/**
* For embedded 'many' properties we need a FetchPath relative to the root which is used to
* build and replace the embedded list.
*/
FetchPath embeddedManyRoot(String path);
/**
* Return a 'raw' property mapped for the given property.
* If none exists the given property is returned.
*/
String rawProperty(String property);
/**
* Store the bean in the doc store index.
* <p>
* This somewhat assumes the bean is fetched with appropriate path properties
* to match the expected document structure.
*/
void index(Object idValue, T bean, DocUpdateContext txn) throws IOException;
/**
* Add a delete by Id to the doc store.
*/
void deleteById(Object idValue, DocUpdateContext txn) throws IOException;
/**
* Add a embedded document update to the doc store.
*
* @param idValue the Id value of the bean holding the embedded document
* @param embeddedProperty the embedded property
* @param embeddedRawContent the content of the embedded document in JSON form
* @param txn the doc store transaction to add the update to
*/
void updateEmbedded(Object idValue, String embeddedProperty, String embeddedRawContent, DocUpdateContext txn) throws IOException;
}
@@ -2,15 +2,12 @@ package io.ebean.plugin;
import io.ebean.Query;
import io.ebean.config.dbplatform.IdType;
import io.ebean.docstore.DocMapping;
import io.ebean.event.BeanFindController;
import io.ebean.event.BeanPersistController;
import io.ebean.event.BeanPersistListener;
import io.ebean.event.BeanQueryAdapter;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
/**
* Information and methods on BeanDescriptors made available to plugins.
@@ -145,73 +142,4 @@ public interface BeanType<T> {
*/
IdType idType();
/**
* Return true if this bean type has doc store backing.
*/
boolean isDocStoreMapped();
/**
* Return the DocumentMapping for this bean type.
* <p>
* This is the document structure and mapping options for how this bean type is mapped
* for the document store.
* </p>
*/
DocMapping docMapping();
/**
* Return the doc store queueId for this bean type.
*/
String docStoreQueueId();
/**
* Return the doc store support for this bean type.\
*/
BeanDocType<T> docStore();
/**
* Add the discriminator value to the query if needed.
*/
void addInheritanceWhere(Query<?> query);
/**
* Return the root bean type for an inheritance hierarchy.
*/
BeanType<?> root();
/**
* Return true if this bean type has an inheritance hierarchy.
*/
boolean hasInheritance();
/**
* Return true if this object is the root level object in its entity
* inheritance.
*/
boolean isInheritanceRoot();
/**
* Returns all direct children of this beantype
*/
List<BeanType<?>> inheritanceChildren();
/**
* Returns the parent in inheritance hierarchy
*/
BeanType<?> inheritanceParent();
/**
* Visit all children recursively
*/
void visitAllInheritanceChildren(Consumer<BeanType<?>> visitor);
/**
* Return the discriminator column.
*/
String discColumn();
/**
* Create a bean given the discriminator value.
*/
T createBeanUsingDisc(Object discValue);
}
@@ -38,11 +38,6 @@ public interface SpiServer extends Database {
*/
List<? extends BeanType<?>> beanTypes(String baseTableName);
/**
* Return the bean type for a given doc store queueId.
*/
BeanType<?> beanTypeForQueueId(String queueId);
/**
* Return a BeanLoader.
*/
@@ -1,98 +0,0 @@
package io.ebean.search;
/**
* Options for the text match and multi match expressions.
*/
public abstract class AbstractMatch {
protected boolean operatorAnd;
protected String analyzer;
protected double boost;
protected String minShouldMatch;
protected int maxExpansions;
protected String zeroTerms;
protected double cutoffFrequency;
protected String fuzziness;
protected int prefixLength;
protected String rewrite;
/**
* Return true if using the AND operator otherwise using the OR operator.
*/
public boolean isOperatorAnd() {
return operatorAnd;
}
/**
* Return the boost.
*/
public double getBoost() {
return boost;
}
/**
* Return the minimum should match.
*/
public String getMinShouldMatch() {
return minShouldMatch;
}
/**
* Return the zero terms option.
*/
public String getZeroTerms() {
return zeroTerms;
}
/**
* Return the cutoff frequency.
*/
public double getCutoffFrequency() {
return cutoffFrequency;
}
/**
* Return the max expansions.
*/
public int getMaxExpansions() {
return maxExpansions;
}
/**
* Return the analyzer.
*/
public String getAnalyzer() {
return analyzer;
}
/**
* Return the fuzziness.
*/
public String getFuzziness() {
return fuzziness;
}
/**
* Return the prefix length.
*/
public int getPrefixLength() {
return prefixLength;
}
/**
* Return the rewrite option.
*/
public String getRewrite() {
return rewrite;
}
}
@@ -1,117 +0,0 @@
package io.ebean.search;
/**
* Options for the text match expression.
*/
public class Match extends AbstractMatch {
protected boolean phrase;
protected boolean phrasePrefix;
public Match() {
}
/**
* Set this to be a "Phrase" type expression.
*/
public Match phrase() {
phrase = true;
return this;
}
/**
* Set this to be a "Phrase Prefix" type expression.
*/
public Match phrasePrefix() {
phrasePrefix = true;
return this;
}
/**
* Use the AND operator (rather than OR).
*/
public Match opAnd() {
operatorAnd = true;
return this;
}
/**
* Use the OR operator (rather than AND).
*/
public Match opOr() {
operatorAnd = false;
return this;
}
/**
* Set the zero terms.
*/
public Match zeroTerms(String zeroTerms) {
this.zeroTerms = zeroTerms;
return this;
}
/**
* Set the cutoff frequency.
*/
public Match cutoffFrequency(double cutoffFrequency) {
this.cutoffFrequency = cutoffFrequency;
return this;
}
/**
* Set the max expansions (for phrase prefix only).
*/
public Match maxExpansions(int maxExpansions) {
this.maxExpansions = maxExpansions;
return this;
}
/**
* Set the Analyzer to use for this expression.
*/
public Match analyzer(String analyzer) {
this.analyzer = analyzer;
return this;
}
/**
* Set the boost.
*/
public Match boost(double boost) {
this.boost = boost;
return this;
}
/**
* Set the rewrite to use.
*/
public Match minShouldMatch(String minShouldMatch) {
this.minShouldMatch = minShouldMatch;
return this;
}
/**
* Set the rewrite to use.
*/
public Match rewrite(String rewrite) {
this.rewrite = rewrite;
return this;
}
/**
* Return true if this is a phrase query.
*/
public boolean isPhrase() {
return phrase;
}
/**
* Return true if this is a phrase prefix query.
*/
public boolean isPhrasePrefix() {
return phrasePrefix;
}
}
@@ -1,148 +0,0 @@
package io.ebean.search;
/**
* Options for the text match expression.
*/
public class MultiMatch extends AbstractMatch {
/**
* The MultiMatch type.
*/
public enum Type {
BEST_FIELDS,
MOST_FIELDS,
CROSS_FIELDS,
PHRASE,
PHRASE_PREFIX
}
protected final String[] fields;
protected Type type = Type.BEST_FIELDS;
protected double tieBreaker;
/**
* Create with the given fields.
*/
public static MultiMatch fields(String... fields) {
return new MultiMatch(fields);
}
/**
* Construct with a set of fields.
*/
public MultiMatch(String... fields) {
this.fields = fields;
}
/**
* Set the type of query.
*/
public MultiMatch type(Type type) {
this.type = type;
return this;
}
/**
* Set the tieBreaker to use.
*/
public MultiMatch tieBreaker(double tieBreaker) {
this.tieBreaker = tieBreaker;
return this;
}
/**
* Use the AND operator (rather than OR).
*/
public MultiMatch opAnd() {
operatorAnd = true;
return this;
}
/**
* Use the OR operator (rather than AND).
*/
public MultiMatch opOr() {
operatorAnd = false;
return this;
}
/**
* Set the minimum should match value.
*/
public MultiMatch minShouldMatch(String minShouldMatch) {
this.minShouldMatch = minShouldMatch;
return this;
}
/**
* Set the boost.
*/
public MultiMatch boost(double boost) {
this.boost = boost;
return this;
}
/**
* Set the zero terms.
*/
public MultiMatch zeroTerms(String zeroTerms) {
this.zeroTerms = zeroTerms;
return this;
}
/**
* Set the cutoff frequency.
*/
public MultiMatch cutoffFrequency(double cutoffFrequency) {
this.cutoffFrequency = cutoffFrequency;
return this;
}
/**
* Set the max expansions (for phrase prefix only).
*/
public MultiMatch maxExpansions(int maxExpansions) {
this.maxExpansions = maxExpansions;
return this;
}
/**
* Set the Analyzer to use for this expression.
*/
public MultiMatch analyzer(String analyzer) {
this.analyzer = analyzer;
return this;
}
/**
* Set the rewrite to use.
*/
public MultiMatch rewrite(String rewrite) {
this.rewrite = rewrite;
return this;
}
/**
* Return the type.
*/
public Type getType() {
return type;
}
/**
* Return the fields to search.
*/
public String[] getFields() {
return fields;
}
/**
* Return the tie breaker.
*/
public double getTieBreaker() {
return tieBreaker;
}
}
@@ -1,139 +0,0 @@
package io.ebean.search;
/**
* Text common terms query.
* <p>
* This maps to an ElasticSearch "common terms query".
* </p>
* <pre>{@code
*
* TextCommonTerms options = new TextCommonTerms()
* .cutoffFrequency(0.001)
* .minShouldMatch("50%")
* .lowFreqOperatorAnd(true)
* .highFreqOperatorAnd(true);
*
* List<Customer> customers = database.find(Customer.class)
* .text()
* .textCommonTerms("the brown", options)
* .findList();
*
* }</pre>
* <pre>{@code
*
* // ElasticSearch expression
*
* "common": {
* "body": {
* "query": "the brown",
* "cutoff_frequency": 0.001,
* "low_freq_operator": "and",
* "high_freq_operator": "and",
* "minimum_should_match": "50%"
* }
* }
*
* }</pre>
*/
public class TextCommonTerms {
protected double cutoffFrequency;
protected boolean lowFreqOperatorAnd;
protected boolean highFreqOperatorAnd;
protected String minShouldMatch;
protected String minShouldMatchLowFreq;
protected String minShouldMatchHighFreq;
/**
* Set the cutoff frequency.
*/
public TextCommonTerms cutoffFrequency(double cutoffFrequency) {
this.cutoffFrequency = cutoffFrequency;
return this;
}
/**
* Set to true if low frequency terms should use AND operator.
*/
public TextCommonTerms lowFreqOperatorAnd(boolean opAnd) {
this.lowFreqOperatorAnd = opAnd;
return this;
}
/**
* Set to true if high frequency terms should use AND operator.
*/
public TextCommonTerms highFreqOperatorAnd(boolean opAnd) {
this.highFreqOperatorAnd = opAnd;
return this;
}
/**
* Set the minimum should match.
*/
public TextCommonTerms minShouldMatch(String minShouldMatch) {
this.minShouldMatch = minShouldMatch;
return this;
}
/**
* Set the minimum should match for low frequency terms.
*/
public TextCommonTerms minShouldMatchLowFreq(String minShouldMatchLowFreq) {
this.minShouldMatchLowFreq = minShouldMatchLowFreq;
return this;
}
/**
* Set the minimum should match for high frequency terms.
*/
public TextCommonTerms minShouldMatchHighFreq(String minShouldMatchHighFreq) {
this.minShouldMatchHighFreq = minShouldMatchHighFreq;
return this;
}
/**
* Return true if low freq should use the AND operator.
*/
public boolean isLowFreqOperatorAnd() {
return lowFreqOperatorAnd;
}
/**
* Return true if high freq should use the AND operator.
*/
public boolean isHighFreqOperatorAnd() {
return highFreqOperatorAnd;
}
/**
* Return the cutoff frequency.
*/
public double getCutoffFrequency() {
return cutoffFrequency;
}
/**
* Return the minimum to match.
*/
public String getMinShouldMatch() {
return minShouldMatch;
}
/**
* Return the minimum to match for high frequency.
*/
public String getMinShouldMatchHighFreq() {
return minShouldMatchHighFreq;
}
/**
* Return the minimum to match for low frequency.
*/
public String getMinShouldMatchLowFreq() {
return minShouldMatchLowFreq;
}
}
@@ -1,398 +0,0 @@
package io.ebean.search;
/**
* Text query string options.
* <p>
* This maps to an ElasticSearch "query string query".
* </p>
* <pre>{@code
*
* TextQueryString options = new TextQueryString()
* .analyzeWildcard(true)
* .fields("name")
* .lenient(true)
* .opAnd();
*
* List<Customer> customers = database.find(Customer.class)
* .text()
* .textSimple("quick brown", options)
* .findList();
*
* }</pre>
* <pre>{@code
*
* // just use default options
* TextQueryString options = new TextQueryString();
*
* List<Customer> customers = database.find(Customer.class)
* .text()
* .textSimple("quick brown", options)
* .findList();
*
* }</pre>
*/
public class TextQueryString {
public static final int DEFAULT_FUZZY_MAX_EXPANSIONS = 50;
protected final String[] fields;
/**
* Only used when multiple fields set.
*/
protected boolean useDisMax = true;
/**
* Only used when multiple fields set.
*/
protected double tieBreaker;
protected String defaultField;
protected boolean operatorAnd;
protected String analyzer;
protected boolean allowLeadingWildcard = true;
protected boolean lowercaseExpandedTerms = true;
protected int fuzzyMaxExpansions = DEFAULT_FUZZY_MAX_EXPANSIONS;
protected String fuzziness;
protected int fuzzyPrefixLength;
protected double phraseSlop;
protected double boost;
protected boolean analyzeWildcard;
protected boolean autoGeneratePhraseQueries;
protected String minShouldMatch;
protected boolean lenient;
protected String locale;
protected String timeZone;
protected String rewrite;
/**
* Create with given fields.
*/
public static TextQueryString fields(String... fields) {
return new TextQueryString(fields);
}
/**
* Construct with the fields to use.
*/
public TextQueryString(String... fields) {
this.fields = fields;
}
/**
* Use the AND operator (rather than OR).
*/
public TextQueryString opAnd() {
this.operatorAnd = true;
return this;
}
/**
* Use the OR operator (rather than AND).
*/
public TextQueryString opOr() {
this.operatorAnd = false;
return this;
}
/**
* Set the locale.
*/
public TextQueryString locale(String locale) {
this.locale = locale;
return this;
}
/**
* Set lenient mode.
*/
public TextQueryString lenient(boolean lenient) {
this.lenient = lenient;
return this;
}
/**
* Set the minimum should match.
*/
public TextQueryString minShouldMatch(String minShouldMatch) {
this.minShouldMatch = minShouldMatch;
return this;
}
/**
* Set the analyzer.
*/
public TextQueryString analyzer(String analyzer) {
this.analyzer = analyzer;
return this;
}
/**
* Set useDisMax option (when multiple fields only).
*/
public TextQueryString useDisMax(boolean useDisMax) {
this.useDisMax = useDisMax;
return this;
}
/**
* Set tieBreaker option (when multiple fields only).
*/
public TextQueryString tieBreaker(double tieBreaker) {
this.tieBreaker = tieBreaker;
return this;
}
/**
* Set the default field.
*/
public TextQueryString defaultField(String defaultField) {
this.defaultField = defaultField;
return this;
}
/**
* Set allow leading wildcard mode.
*/
public TextQueryString allowLeadingWildcard(boolean allowLeadingWildcard) {
this.allowLeadingWildcard = allowLeadingWildcard;
return this;
}
/**
* Set lowercase expanded terms mode.
*/
public TextQueryString lowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
this.lowercaseExpandedTerms = lowercaseExpandedTerms;
return this;
}
/**
* Set fuzzy max expansions.
*/
public TextQueryString fuzzyMaxExpansions(int fuzzyMaxExpansions) {
this.fuzzyMaxExpansions = fuzzyMaxExpansions;
return this;
}
/**
* Set fuzziness.
*/
public TextQueryString fuzziness(String fuzziness) {
this.fuzziness = fuzziness;
return this;
}
/**
* Set the fuzzy prefix length.
*/
public TextQueryString fuzzyPrefixLength(int fuzzyPrefixLength) {
this.fuzzyPrefixLength = fuzzyPrefixLength;
return this;
}
/**
* Set the phrase slop.
*/
public TextQueryString phraseSlop(double phraseSlop) {
this.phraseSlop = phraseSlop;
return this;
}
/**
* Set the boost.
*/
public TextQueryString boost(double boost) {
this.boost = boost;
return this;
}
/**
* Set the analyze wildcard mode.
*/
public TextQueryString analyzeWildcard(boolean analyzeWildcard) {
this.analyzeWildcard = analyzeWildcard;
return this;
}
/**
* Set the auto generate phrase queries mode.
*/
public TextQueryString autoGeneratePhraseQueries(boolean autoGeneratePhraseQueries) {
this.autoGeneratePhraseQueries = autoGeneratePhraseQueries;
return this;
}
/**
* Set the time zone.
*/
public TextQueryString timeZone(String timeZone) {
this.timeZone = timeZone;
return this;
}
/**
* Set the rewrite option.
*/
public TextQueryString rewrite(String rewrite) {
this.rewrite = rewrite;
return this;
}
/**
* Return the rewrite option.
*/
public String getRewrite() {
return rewrite;
}
/**
* Return the fields.
*/
public String[] getFields() {
return fields;
}
/**
* Return true if AND is the default operator.
*/
public boolean isOperatorAnd() {
return operatorAnd;
}
/**
* Return the analyzer.
*/
public String getAnalyzer() {
return analyzer;
}
/**
* Return the locale.
*/
public String getLocale() {
return locale;
}
/**
* Return lenient mode.
*/
public boolean isLenient() {
return lenient;
}
/**
* Return the minimum should match.
*/
public String getMinShouldMatch() {
return minShouldMatch;
}
/**
* Return the useDixMax mode.
*/
public boolean isUseDisMax() {
return useDisMax;
}
/**
* Return the tie breaker.
*/
public double getTieBreaker() {
return tieBreaker;
}
/**
* Return the default field.
*/
public String getDefaultField() {
return defaultField;
}
/**
* Return the allow leading wildcard mode.
*/
public boolean isAllowLeadingWildcard() {
return allowLeadingWildcard;
}
/**
* Return the lowercase expanded terms mode.
*/
public boolean isLowercaseExpandedTerms() {
return lowercaseExpandedTerms;
}
/**
* Return the fuzzy max expansions.
*/
public int getFuzzyMaxExpansions() {
return fuzzyMaxExpansions;
}
/**
* Return the fuzziness.
*/
public String getFuzziness() {
return fuzziness;
}
/**
* Return the fuzzy prefix length.
*/
public int getFuzzyPrefixLength() {
return fuzzyPrefixLength;
}
/**
* Return the phrase slop.
*/
public double getPhraseSlop() {
return phraseSlop;
}
/**
* Return the analyze wildcard mode.
*/
public boolean isAnalyzeWildcard() {
return analyzeWildcard;
}
/**
* Return the boost.
*/
public double getBoost() {
return boost;
}
/**
* Return the auto generate phase queries mode.
*/
public boolean isAutoGeneratePhraseQueries() {
return autoGeneratePhraseQueries;
}
/**
* Return the time zone.
*/
public String getTimeZone() {
return timeZone;
}
}
@@ -1,193 +0,0 @@
package io.ebean.search;
/**
* Simple text query options.
* <p>
* This maps to an ElasticSearch "simple text query".
* </p>
* <pre>{@code
*
* TextSimple options = new TextSimple()
* .analyzeWildcard(true)
* .fields("name")
* .lenient(true)
* .opAnd();
*
* List<Customer> customers = database.find(Customer.class)
* .text()
* .textSimple("quick brown", options)
* .findList();
*
* }</pre>
*/
public class TextSimple {
protected String[] fields;
protected boolean operatorAnd;
protected String analyzer;
protected String flags;
protected boolean lowercaseExpandedTerms = true;
protected boolean analyzeWildcard;
protected String locale;
protected boolean lenient;
protected String minShouldMatch;
/**
* Construct
*/
public TextSimple() {
}
/**
* Set the fields.
*/
public TextSimple fields(String... fields) {
this.fields = fields;
return this;
}
/**
* Use AND as the default operator.
*/
public TextSimple opAnd() {
this.operatorAnd = true;
return this;
}
/**
* Use OR as the default operator.
*/
public TextSimple opOr() {
this.operatorAnd = false;
return this;
}
/**
* Set the analyzer
*/
public TextSimple analyzer(String analyzer) {
this.analyzer = analyzer;
return this;
}
/**
* Set the flags.
*/
public TextSimple flags(String flags) {
this.flags = flags;
return this;
}
/**
* Set the false to not use lowercase expanded terms.
*/
public TextSimple lowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
this.lowercaseExpandedTerms = lowercaseExpandedTerms;
return this;
}
/**
* Set to true to use analyze wildcard.
*/
public TextSimple analyzeWildcard(boolean analyzeWildcard) {
this.analyzeWildcard = analyzeWildcard;
return this;
}
/**
* Set the locale.
*/
public TextSimple locale(String locale) {
this.locale = locale;
return this;
}
/**
* Set the lenient mode.
*/
public TextSimple lenient(boolean lenient) {
this.lenient = lenient;
return this;
}
/**
* Set the minimum should match.
*/
public TextSimple minShouldMatch(String minShouldMatch) {
this.minShouldMatch = minShouldMatch;
return this;
}
/**
* Return lenient mode.
*/
public boolean isLenient() {
return lenient;
}
/**
* Return true to analyse wildcard.
*/
public boolean isAnalyzeWildcard() {
return analyzeWildcard;
}
/**
* Return lowercase expanded terms mode.
*/
public boolean isLowercaseExpandedTerms() {
return lowercaseExpandedTerms;
}
/**
* Return true if the default operator should be AND.
*/
public boolean isOperatorAnd() {
return operatorAnd;
}
/**
* Return the analyzer to use.
*/
public String getAnalyzer() {
return analyzer;
}
/**
* Return the fields.
*/
public String[] getFields() {
return fields;
}
/**
* Return the locale.
*/
public String getLocale() {
return locale;
}
/**
* Return the flags.
*/
public String getFlags() {
return flags;
}
/**
* Return the minimum should match.
*/
public String getMinShouldMatch() {
return minShouldMatch;
}
}
@@ -1,4 +0,0 @@
/**
* Provides text search expressions like Match, TextQueryString etc.
*/
package io.ebean.search;
-3
View File
@@ -30,13 +30,10 @@ module io.ebean.api {
exports io.ebean.config;
exports io.ebean.config.dbplatform;
exports io.ebean.event;
exports io.ebean.event.readaudit;
exports io.ebean.event.changelog;
exports io.ebean.common;
exports io.ebean.docstore;
exports io.ebean.plugin;
exports io.ebean.metric;
exports io.ebean.search;
exports io.ebean.service;
exports io.ebean.text;
exports io.ebean.text.json;
-32
View File
@@ -49,18 +49,6 @@
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>14.0.0</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.13.1</version>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
@@ -234,26 +222,6 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<doctitle>Ebean 12</doctitle>
<overview>src/main/java/io/ebean/overview.html</overview>
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform</excludePackageNames>
<linksource>true</linksource>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -51,8 +51,4 @@ public interface LoadContext {
*/
void register(String path, BeanPropertyAssocMany<?> many, BeanCollection<?> bc);
/**
* Use soft-references for streaming queries, so unreachable entries can be garbage collected.
*/
void useReferences(boolean useReferences);
}
@@ -43,5 +43,4 @@ public interface LoadManyBuffer {
void configureQuery(SpiQuery<?> query);
boolean isUseDocStore();
}
@@ -99,7 +99,7 @@ public final class LoadManyRequest extends LoadRequest {
query.where().raw(extraWhere.replace("${ta}", "t0").replace("${mta}", "int_"));
}
query.setLazyLoadForParents(many);
many.addWhereParentIdIn(query, parentIdList(server), loadContext.isUseDocStore());
many.addWhereParentIdIn(query, parentIdList(server));
query.setPersistenceContext(loadContext.persistenceContext());
query.setLoadDescription(lazy ? "lazy" : "query", description());
if (lazy) {
@@ -4,8 +4,6 @@ import io.avaje.lang.Nullable;
import io.ebean.*;
import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.CallOrigin;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetricVisitor;
import io.ebean.plugin.SpiServer;
import io.ebeaninternal.api.SpiQuery.Type;
@@ -106,11 +104,6 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
*/
BeanDescriptor<?> descriptorById(String className);
/**
* Return BeanDescriptor using it's unique doc store queueId.
*/
BeanDescriptor<?> descriptorByQueueId(String queueId);
/**
* Return BeanDescriptors mapped to this table.
*/
@@ -195,17 +188,6 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
*/
boolean isSupportedType(java.lang.reflect.Type genericType);
/**
* Return the ReadAuditLogger to use for logging all read audit events.
*/
ReadAuditLogger readAuditLogger();
/**
* Return the ReadAuditPrepare used to populate the read audit events with
* user context information (user id, user ip address etc).
*/
ReadAuditPrepare readAuditPrepare();
/**
* Return the DataTimeZone to use when reading/writing timestamps via JDBC.
*/
@@ -3,9 +3,6 @@ package io.ebeaninternal.api;
import io.ebean.Expression;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.expression.DocQueryContext;
import java.io.IOException;
/**
@@ -21,16 +18,6 @@ public interface SpiExpression extends Expression {
*/
void simplify();
/**
* Write the expression as an elastic search expression.
*/
void writeDocQuery(DocQueryContext context) throws IOException;
/**
* Return the nested path for this expression.
*/
String nestedPath(BeanDescriptor<?> desc);
/**
* Process "Many" properties populating ManyWhereJoins.
* <p>
@@ -2,7 +2,6 @@ package io.ebeaninternal.api;
import io.ebean.ExpressionList;
import io.ebean.Junction;
import io.ebeaninternal.server.expression.DocQueryContext;
import java.io.IOException;
import java.util.List;
@@ -32,11 +31,6 @@ public interface SpiExpressionList<T> extends ExpressionList<T>, SpiExpression {
*/
boolean isEmpty();
/**
* Write the top level where expressions taking into account possible extra idEquals expression.
*/
void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException;
/**
* Apply firstRow maxRows limits on the filterMany query.
*/
@@ -1,17 +1,10 @@
package io.ebeaninternal.api;
import io.ebean.Junction;
import io.ebeaninternal.server.expression.DocQueryContext;
import java.io.IOException;
/**
* SPI methods for Junction.
*/
public interface SpiJunction<T> extends Junction<T> {
/**
* Write the Junction taking into account it is implied.
*/
void writeDocQueryJunction(DocQueryContext context) throws IOException;
}
@@ -11,7 +11,6 @@ import io.ebean.Query;
import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.PersistenceContext;
import io.ebean.event.readaudit.ReadEvent;
import io.ebean.plugin.BeanType;
import io.ebeaninternal.server.autotune.ProfilingListener;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
@@ -170,11 +169,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
SOFT_DELETED(false),
/**
* Query runs against draft tables.
*/
DRAFT(false),
/**
* Query runs against current data (normal).
*/
@@ -292,17 +286,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
SpiRawSql rawSql();
/**
* Return true if this query should be executed against the doc store.
*/
boolean isUseDocStore();
/**
* For doc store query return the document index name to search against.
* This is for partitioned indexes (like daily logstash indexes etc).
*/
String getDocIndexName();
/**
* Return the PersistenceContextScope that this query should use.
* <p>
@@ -377,11 +360,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
boolean isAsOfQuery();
/**
* Return true if this is a 'As Draft' query.
*/
boolean isAsDraft();
/**
* Return true if this query includes soft deleted rows.
*/
@@ -510,11 +488,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
NaturalKeyBindParam naturalKeyBindParam();
/**
* Prepare the query for docstore execution with nested paths.
*/
void prepareDocNested();
/**
* Set the query to be a delete query.
*/
@@ -730,11 +703,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
SpiExpressionList<T> havingExpressions();
/**
* Return the text expressions.
*/
SpiExpressionList<T> textExpression();
/**
* Returns true if either firstRow or maxRows has been set.
*/
@@ -801,11 +769,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
boolean tuneFetchProperties(OrmQueryDetail detail);
/**
* If this is a RawSql based entity set the default RawSql if not set.
*/
void setDefaultRawSqlIfRequired();
/**
* Set to true if this query has been tuned by autoTune.
*/
@@ -883,21 +846,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
int bufferFetchSizeHint();
/**
* Return true if read auditing is disabled on this query.
*/
boolean isDisableReadAudit();
/**
* Set the readEvent for future queries (as prepared in foreground thread).
*/
void setFutureFetchAudit(ReadEvent event);
/**
* Read the readEvent for future queries (null otherwise).
*/
ReadEvent futureFetchAudit();
/**
* Return the base table to use if user defined on the query.
*/
@@ -9,7 +9,6 @@ import io.ebeaninternal.server.core.PersistDeferredRelationship;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.persist.BatchControl;
import io.ebeaninternal.server.transaction.ProfileStream;
import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
@@ -103,19 +102,6 @@ public interface SpiTransaction extends Transaction {
*/
Boolean isUpdateAllLoadedProperties();
/**
* Return the batchSize specifically set for this transaction or 0.
* <p>
* Returning 0 implies to use the system wide default batch size.
*/
DocStoreMode docStoreMode();
/**
* Return the batch size to us for ElasticSearch Bulk API calls
* as a result of this transaction.
*/
int getDocStoreBatchSize();
/**
* Return the batchSize specifically set for this transaction or 0.
* <p>
@@ -287,11 +273,6 @@ public interface SpiTransaction extends Transaction {
*/
void sendChangeLog(ChangeSet changeSet);
/**
* Return a document store transaction.
*/
DocStoreTransaction docStoreTransaction();
/**
* Set the current Tenant Id.
*/
@@ -2,14 +2,12 @@ package io.ebeaninternal.api;
import io.ebean.ProfileLocation;
import io.ebean.TransactionCallback;
import io.ebean.annotation.DocStoreMode;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeSet;
import io.ebeaninternal.server.core.PersistDeferredRelationship;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.persist.BatchControl;
import io.ebeaninternal.server.transaction.ProfileStream;
import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
@@ -112,32 +110,6 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
return transaction.tenantId();
}
@Override
public DocStoreTransaction docStoreTransaction() {
return transaction.docStoreTransaction();
}
@Override
public DocStoreMode docStoreMode() {
return transaction.docStoreMode();
}
@Override
public void setDocStoreMode(DocStoreMode mode) {
transaction.setDocStoreMode(mode);
}
@Override
public int getDocStoreBatchSize() {
return transaction.getDocStoreBatchSize();
}
@Override
public void setDocStoreBatchSize(int batchSize) {
transaction.setDocStoreBatchSize(batchSize);
}
@Override
public boolean isLogSql() {
return transaction.isLogSql();
@@ -6,7 +6,6 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.transaction.DeleteByIdMap;
import io.ebeaninternal.server.transaction.TransactionManager;
import io.ebeanservice.docstore.api.DocStoreUpdates;
import java.io.Serializable;
import java.util.ArrayList;
@@ -125,18 +124,6 @@ public final class TransactionEvent implements Serializable {
return changeSet;
}
/**
* Add any relevant PersistRequestBean's to DocStoreUpdates for later processing.
*/
public void addDocStoreUpdates(DocStoreUpdates docStoreUpdates) {
List<PersistRequestBean<?>> requests = listenerNotify();
if (requests != null) {
for (PersistRequestBean<?> persistRequestBean : requests) {
persistRequestBean.addDocStoreUpdates(docStoreUpdates);
}
}
}
/**
* Return the CacheChangeSet that we add cache notification messages to.
* <p>
@@ -15,7 +15,6 @@ public final class CachedBeanData implements Externalizable {
private long whenCreated;
private long version;
private String discValue;
private Map<String, Object> data;
/**
* The sharable bean is effectively transient (near cache only).
@@ -25,10 +24,9 @@ public final class CachedBeanData implements Externalizable {
/**
* Construct from a loaded bean.
*/
public CachedBeanData(Object sharableBean, String discValue, Map<String, Object> data, long version) {
public CachedBeanData(Object sharableBean, Map<String, Object> data, long version) {
this.whenCreated = System.currentTimeMillis();
this.sharableBean = sharableBean;
this.discValue = discValue;
this.data = data;
this.version = version;
}
@@ -43,11 +41,6 @@ public final class CachedBeanData implements Externalizable {
public void writeExternal(ObjectOutput out) throws IOException {
out.writeLong(version);
out.writeLong(whenCreated);
boolean hasDisc = discValue != null;
out.writeBoolean(hasDisc);
if (hasDisc) {
out.writeUTF(discValue);
}
out.writeInt(data.size());
for (Map.Entry<String, Object> entry : data.entrySet()) {
out.writeUTF(entry.getKey());
@@ -59,9 +52,6 @@ public final class CachedBeanData implements Externalizable {
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
version = in.readLong();
whenCreated = in.readLong();
if (in.readBoolean()) {
discValue = in.readUTF();
}
data = new LinkedHashMap<>();
int count = in.readInt();
for (int i = 0; i < count; i++) {
@@ -85,7 +75,7 @@ public final class CachedBeanData implements Externalizable {
Map<String, Object> copy = new HashMap<>();
copy.putAll(data);
copy.putAll(changes);
return new CachedBeanData(null, discValue, copy, version);
return new CachedBeanData(null, copy, version);
}
/**
@@ -102,13 +92,6 @@ public final class CachedBeanData implements Externalizable {
return version;
}
/**
* Return the raw discriminator value.
*/
public String getDiscValue() {
return discValue;
}
/**
* Return a sharable (immutable read only) bean. Near cache only use.
*/
@@ -41,7 +41,7 @@ public final class CachedBeanDataFromBean {
long version = desc.getVersion(bean);
EntityBean sharableBean = createSharableBean(desc, bean, ebi);
return new CachedBeanData(sharableBean, desc.discValue(), data, version);
return new CachedBeanData(sharableBean, data, version);
}
private static EntityBean createSharableBean(BeanDescriptor<?> desc, EntityBean bean, EntityBeanIntercept beanEbi) {
@@ -14,9 +14,6 @@ public final class CachedBeanDataToBean {
// any future lazy loading skips L2 bean cache
ebi.setLoadedFromCache(true);
BeanProperty idProperty = desc.idProperty();
if (desc.inheritInfo() != null) {
desc = desc.inheritInfo().readType(bean.getClass()).desc();
}
if (idProperty != null) {
// load the id property
loadProperty(bean, cacheBeanData, ebi, idProperty, context);
@@ -1,54 +0,0 @@
package io.ebeaninternal.server.cache;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* Bean Id value plus discriminator type.
* <p>
* Put into L2 cache such that we know the type of a bean with inheritance.
*/
public final class CachedBeanId implements Externalizable {
private String discValue;
private Object id;
public CachedBeanId(String discValue, Object id) {
this.discValue = discValue;
this.id = id;
}
/**
* Construct from serialisation.
*/
public CachedBeanId() {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(discValue);
out.writeObject(id);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
discValue = in.readUTF();
id = in.readObject();
}
@Override
public String toString() {
return discValue + ":" + id;
}
public String getDiscValue() {
return discValue;
}
public Object getId() {
return id;
}
}
@@ -178,12 +178,11 @@ final class DefaultBeanLoader {
desc.contextPut(pc, id, bean);
ebi.setPersistenceContext(pc);
}
boolean draft = desc.isDraftInstance(bean);
if (embeddedOwnerIndex == -1) {
if (desc.lazyLoadMany(ebi)) {
return;
}
if (!draft && Mode.LAZYLOAD_BEAN == mode && desc.isBeanCaching()) {
if (Mode.LAZYLOAD_BEAN == mode && desc.isBeanCaching()) {
// lazy loading and the bean cache is active
if (desc.cacheBeanLoad(bean, ebi, id, pc)) {
return;
@@ -192,9 +191,7 @@ final class DefaultBeanLoader {
}
SpiQuery<?> query = server.createQuery(desc.type());
query.setLazyLoadProperty(ebi.lazyLoadProperty());
if (draft) {
query.asDraft();
} else if (mode == SpiQuery.Mode.LAZYLOAD_BEAN && desc.isSoftDelete()) {
if (mode == SpiQuery.Mode.LAZYLOAD_BEAN && desc.isSoftDelete()) {
query.setIncludeSoftDeletes();
}
if (embeddedOwnerIndex > -1) {
@@ -92,16 +92,12 @@ public final class DefaultContainer implements SpiContainer {
BootupClasses bootupClasses = bootupClasses(config);
boolean online = true;
if (config.isDocStoreOnly()) {
config.databasePlatform(new DatabasePlatform());
} else {
TenantMode tenantMode = config.getTenantMode();
if (TenantMode.DB != tenantMode) {
setDataSource(config);
if (!tenantMode.isDynamicDataSource()) {
// check the autoCommit and Transaction Isolation
online = checkDataSource(config);
}
TenantMode tenantMode = config.getTenantMode();
if (TenantMode.DB != tenantMode) {
setDataSource(config);
if (!tenantMode.isDynamicDataSource()) {
// check the autoCommit and Transaction Isolation
online = checkDataSource(config);
}
}
@@ -13,8 +13,6 @@ import io.ebean.config.*;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.event.BeanPersistController;
import io.ebean.event.ShutdownManager;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.*;
import io.ebean.migration.auto.AutoMigrationRunner;
import io.ebean.plugin.BeanType;
@@ -30,11 +28,9 @@ import io.ebeaninternal.server.core.timezone.DataTimeZone;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.dto.DtoBeanDescriptor;
import io.ebeaninternal.server.dto.DtoBeanManager;
import io.ebeaninternal.server.el.ElFilter;
import io.ebeaninternal.server.grammer.EqlParser;
import io.ebeaninternal.server.query.*;
import io.ebeaninternal.server.querydefn.*;
import io.ebeaninternal.server.rawsql.SpiRawSql;
@@ -43,7 +39,6 @@ import io.ebeaninternal.server.transaction.RemoteTransactionEvent;
import io.ebeaninternal.server.transaction.TransactionManager;
import io.ebeaninternal.util.ParamTypeHelper;
import io.ebeaninternal.util.ParamTypeHelper.TypeInfo;
import io.ebeanservice.docstore.api.DocStoreIntegration;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.NonUniqueResultException;
@@ -93,8 +88,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private final DtoBeanManager dtoBeanManager;
private final BeanDescriptorManager descriptorManager;
private final AutoTuneService autoTuneService;
private final ReadAuditPrepare readAuditPrepare;
private final ReadAuditLogger readAuditLogger;
private final CQueryEngine cqueryEngine;
private final List<Plugin> serverPlugins;
private final SpiDdlGenerator ddlGenerator;
@@ -104,7 +97,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private final DefaultBeanLoader beanLoader;
private final EncryptKeyManager encryptKeyManager;
private final SpiJsonContext jsonContext;
private final DocumentStore documentStore;
private final MetaInfoManager metaInfoManager;
private final CurrentTenantProvider currentTenantProvider;
private final SpiLogManager logManager;
@@ -146,16 +138,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
this.relationalQueryEngine = config.createRelationalQueryEngine();
this.dtoQueryEngine = config.createDtoQueryEngine();
this.autoTuneService = config.createAutoTuneService(this);
this.readAuditPrepare = config.getReadAuditPrepare();
this.readAuditLogger = config.getReadAuditLogger();
this.beanLoader = new DefaultBeanLoader(this);
this.jsonContext = config.createJsonContext(this);
this.dataTimeZone = config.getDataTimeZone();
this.clockService = config.getClockService();
DocStoreIntegration docStoreComponents = config.createDocStoreIntegration(this);
this.transactionManager = config.createTransactionManager(this, docStoreComponents.updateProcessor());
this.documentStore = docStoreComponents.documentStore();
this.transactionManager = config.createTransactionManager(this);
this.queryPlanManager = config.initQueryPlanManager(transactionManager);
this.metaInfoManager = new DefaultMetaInfoManager(this, this.config.getMetricNaming());
this.serverPlugins = config.getPlugins();
@@ -189,9 +177,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
* Execute all the plugins with an online flag indicating the DB is up or not.
*/
public void executePlugins(boolean online) {
if (!config.isDocStoreOnly()) {
ddlGenerator.execute(online);
}
ddlGenerator.execute(online);
for (Plugin plugin : serverPlugins) {
plugin.online(online);
}
@@ -283,16 +269,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return transactionManager.readOnlyDataSource();
}
@Override
public ReadAuditPrepare readAuditPrepare() {
return readAuditPrepare;
}
@Override
public ReadAuditLogger readAuditLogger() {
return readAuditLogger;
}
/**
* Run any initialisation required before registering with the ClusterManager.
*/
@@ -618,25 +594,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return (T) existing;
}
}
InheritInfo inheritInfo = desc.inheritInfo();
if (inheritInfo == null || inheritInfo.isConcrete()) {
return (T) desc.contextRef(pc, null, false, id);
}
return referenceFindOne(type, id, desc);
}
private <T> T referenceFindOne(Class<T> type, Object id, BeanDescriptor<?> desc) {
BeanProperty idProp = desc.idProperty();
if (idProp == null) {
throw new PersistenceException("No ID properties for this type? " + desc);
}
// we actually need to do a query because we don't know the type without the discriminator
// value, just select the id property and discriminator column (auto added)
T bean = find(type).select(idProp.name()).setId(id).findOne();
if (bean == null) {
throw new EntityNotFoundException("Could not find reference bean " + id + " for " + desc);
}
return bean;
return (T) desc.contextRef(pc, null, false, id);
}
@Override
@@ -838,29 +796,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return query;
}
@Override
public <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
BeanDescriptor<T> desc = desc(beanType);
String named = desc.namedQuery(namedQuery);
if (named != null) {
return createQuery(beanType, named);
}
SpiRawSql rawSql = desc.namedRawSql(namedQuery);
if (rawSql != null) {
DefaultOrmQuery<T> query = createQuery(beanType);
query.setRawSql(rawSql);
return query;
}
throw new PersistenceException("No named query called " + namedQuery + " for bean:" + beanType.getName());
}
@Override
public <T> DefaultOrmQuery<T> createQuery(Class<T> beanType, String eql) {
DefaultOrmQuery<T> query = createQuery(beanType);
EqlParser.parse(eql, query);
return query;
}
@Override
public <T> DefaultOrmQuery<T> createQuery(Class<T> beanType) {
return new DefaultOrmQuery<>(desc(beanType), this, expressionFactory);
@@ -877,16 +812,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return new DefaultDtoQuery<>(this, descriptor, sql.trim());
}
@Override
public <T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery) {
DtoBeanDescriptor<T> descriptor = dtoBeanManager.descriptor(dtoType);
String sql = descriptor.namedRawSql(namedQuery);
if (sql == null) {
throw new PersistenceException("No named query called " + namedQuery + " for bean:" + dtoType.getName());
}
return new DefaultDtoQuery<>(this, descriptor, sql);
}
@Override
public <T> DtoQuery<T> findDto(Class<T> dtoType, SpiQuery<?> ormQuery) {
DtoBeanDescriptor<T> descriptor = dtoBeanManager.descriptor(dtoType);
@@ -950,7 +875,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
transaction = currentServerTransaction();
}
if (!query.isRawSql()) {
query.setDefaultRawSqlIfRequired();
if (!query.isAutoTunable() || !autoTuneService.tuneQuery(query)) {
// use deployment FetchType.LAZY/EAGER annotations
// to define the 'default' select clause
@@ -1033,9 +957,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
SpiOrmQueryRequest<T> request = buildQueryRequest(query);
request.prepareQuery();
if (request.isUseDocStore()) {
return docStore().find(request);
}
try {
request.initTransIfRequired();
return (T) request.findId();
@@ -1304,10 +1225,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
spiQuery.usingFuture();
// FutureList query always run in it's own persistence content
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
if (!spiQuery.isDisableReadAudit()) {
BeanDescriptor<T> desc = descriptorManager.descriptor(spiQuery.getBeanType());
desc.readAuditFutureList(spiQuery);
}
// Create a new transaction solely to execute the findList() at some future time
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
@@ -1330,9 +1247,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
if (maxRows == 0) {
throw new PersistenceException("maxRows must be specified for findPagedList() query");
}
if (query.isUseDocStore()) {
return docStore().findPagedList(createQueryRequest(Type.LIST, query));
}
return new LimitOffsetPagedList<>(this, query);
}
@@ -1360,10 +1274,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public <T> void findEach(SpiQuery<T> query, Consumer<T> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
if (request.isUseDocStore()) {
docStore().findEach(request, consumer);
return;
}
request.initTransIfRequired();
request.findEach(consumer);
// no try finally - findEach guarantee's cleanup of the transaction if required
@@ -1372,10 +1282,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public <T> void findEach(SpiQuery<T> query, int batch, Consumer<List<T>> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
// if (request.isUseDocStore()) {
// docStore().findEach(request, consumer);
// return;
// }
request.initTransIfRequired();
request.findEach(batch, consumer);
// no try finally - findEach guarantee's cleanup of the transaction if required
@@ -1384,10 +1290,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public <T> void findEachWhile(SpiQuery<T> query, Predicate<T> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
if (request.isUseDocStore()) {
docStore().findEachWhile(request, consumer);
return;
}
request.initTransIfRequired();
request.findEachWhile(consumer);
// no try finally - findEachWhile guarantee's cleanup of the transaction if required
@@ -1422,9 +1324,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
if (result != null) {
return (List<T>) result;
}
if (request.isUseDocStore()) {
return docStore().findList(request);
}
try {
request.initTransIfRequired();
return request.findList();
@@ -1693,54 +1592,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}, transaction);
}
@Override
public <T> List<T> publish(Query<T> query, @Nullable Transaction transaction) {
return executeInTrans((txn) -> persister.publish(query, txn), transaction);
}
@Nullable
@Override
public <T> T publish(Class<T> beanType, Object id) {
return publish(beanType, id, null);
}
@Override
public <T> List<T> publish(Query<T> query) {
return publish(query, null);
}
@Nullable
@Override
public <T> T publish(Class<T> beanType, Object id, @Nullable Transaction transaction) {
Query<T> query = find(beanType).setId(id);
List<T> liveBeans = publish(query, transaction);
return (liveBeans.size() == 1) ? liveBeans.get(0) : null;
}
@Override
public <T> List<T> draftRestore(Query<T> query, @Nullable Transaction transaction) {
return executeInTrans((txn) -> persister.draftRestore(query, txn), transaction);
}
@Nullable
@Override
public <T> T draftRestore(Class<T> beanType, Object id, @Nullable Transaction transaction) {
Query<T> query = find(beanType).setId(id);
List<T> beans = draftRestore(query, transaction);
return (beans.size() == 1) ? beans.get(0) : null;
}
@Nullable
@Override
public <T> T draftRestore(Class<T> beanType, Object id) {
return draftRestore(beanType, id, null);
}
@Override
public <T> List<T> draftRestore(Query<T> query) {
return draftRestore(query, null);
}
private EntityBean checkEntityBean(Object bean) {
return (EntityBean) Objects.requireNonNull(bean);
}
@@ -2049,16 +1900,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return descriptorManager.beanTypes(tableName);
}
@Override
public BeanType<?> beanTypeForQueueId(String queueId) {
return descriptorByQueueId(queueId);
}
@Override
public BeanDescriptor<?> descriptorByQueueId(String queueId) {
return descriptorManager.descriptorByQueueId(queueId);
}
/**
* Return the SPI bean types for the given bean class.
*/
@@ -2165,11 +2006,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return callStackFactory.createCallOrigin();
}
@Override
public DocumentStore docStore() {
return documentStore;
}
@Override
public JsonContext json() {
// immutable thread safe so return shared instance
@@ -1,69 +0,0 @@
package io.ebeaninternal.server.core;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.dto.DtoNamedQueries;
import io.ebeaninternal.xmapping.api.XmapDto;
import io.ebeaninternal.xmapping.api.XmapEbean;
import io.ebeaninternal.xmapping.api.XmapRawSql;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.lang.System.Logger.Level.ERROR;
/**
* Reads the Xml deployment information.
*/
final class InternalConfigXmlMap {
private final List<XmapEbean> xmlEbeanList;
private final ClassLoader classLoader;
private final Map<Class<?>, DtoNamedQueries> dtoNamedQueries = new HashMap<>();
InternalConfigXmlMap(List<XmapEbean> xmlEbeanList, ClassLoader classLoader) {
this.xmlEbeanList = xmlEbeanList;
this.classLoader = classLoader;
initDtoMapping();
}
void initDtoMapping() {
if (xmlEbeanList != null) {
for (XmapEbean mapping : xmlEbeanList) {
List<XmapDto> dtoList = mapping.getDto();
for (XmapDto dto : dtoList) {
readDtoMapping(dto);
}
}
}
}
/**
* Return the XML deployment information for entity beans.
*/
List<XmapEbean> xmlDeployment() {
return xmlEbeanList;
}
/**
* Return the named queries for Dto beans.
*/
Map<Class<?>, DtoNamedQueries> readDtoMapping() {
return dtoNamedQueries;
}
private void readDtoMapping(XmapDto dto) {
Class<?> dtoClass;
try {
dtoClass = Class.forName(dto.getClazz(), false, classLoader);
} catch (Exception e) {
CoreLog.internal.log(ERROR, "Could not load dto bean class " + dto.getClazz() + " for ebean xml entry");
return;
}
DtoNamedQueries namedQueries = dtoNamedQueries.computeIfAbsent(dtoClass, aClass -> new DtoNamedQueries());
for (XmapRawSql sql : dto.getRawSql()) {
namedQueries.addRawSql(sql.getName(), sql.getQuery());
}
}
}
@@ -11,8 +11,6 @@ import io.ebean.config.dbplatform.DbHistorySupport;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.plugin.Plugin;
import io.ebean.plugin.SpiServer;
import io.ebeaninternal.api.*;
@@ -29,7 +27,6 @@ import io.ebeaninternal.server.core.timezone.*;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import io.ebeaninternal.server.deploy.parse.DeployCreateProperties;
import io.ebeaninternal.server.deploy.parse.DeployInherit;
import io.ebeaninternal.server.deploy.parse.DeployUtil;
import io.ebeaninternal.server.dto.DtoBeanManager;
import io.ebeaninternal.server.expression.DefaultExpressionFactory;
@@ -42,18 +39,10 @@ import io.ebeaninternal.server.persist.DefaultPersister;
import io.ebeaninternal.server.persist.platform.MultiValueBind;
import io.ebeaninternal.server.persist.platform.PostgresMultiValueBind;
import io.ebeaninternal.server.query.*;
import io.ebeaninternal.server.readaudit.DefaultReadAuditLogger;
import io.ebeaninternal.server.readaudit.DefaultReadAuditPrepare;
import io.ebeaninternal.server.json.DJsonContext;
import io.ebeaninternal.server.transaction.*;
import io.ebeaninternal.server.type.DefaultTypeManager;
import io.ebeaninternal.server.type.TypeManager;
import io.ebeaninternal.xmapping.api.XmapEbean;
import io.ebeaninternal.xmapping.api.XmapService;
import io.ebeanservice.docstore.api.DocStoreFactory;
import io.ebeanservice.docstore.api.DocStoreIntegration;
import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import io.ebeanservice.docstore.none.NoneDocStoreFactory;
import java.util.*;
@@ -72,7 +61,6 @@ public final class InternalConfiguration {
private final DatabaseBuilder.Settings config;
private final BootupClasses bootupClasses;
private final DatabasePlatform databasePlatform;
private final DeployInherit deployInherit;
private final TypeManager typeManager;
private final DtoBeanManager dtoBeanManager;
private final ClockService clockService;
@@ -89,7 +77,6 @@ public final class InternalConfiguration {
private final ExpressionFactory expressionFactory;
private final SpiBackgroundExecutor backgroundExecutor;
private final JsonFactory jsonFactory;
private final DocStoreFactory docStoreFactory;
private final List<Plugin> plugins = new ArrayList<>();
private final MultiValueBind multiValueBind;
private final SpiLogManager logManager;
@@ -106,7 +93,6 @@ public final class InternalConfiguration {
this.clockService = new ClockService(config.settings().getClock());
this.tableModState = new TableModState();
this.logManager = initLogManager();
this.docStoreFactory = initDocStoreFactory(service(DocStoreFactory.class));
this.jsonFactory = config.getJsonFactory();
this.clusterManager = clusterManager;
this.backgroundExecutor = backgroundExecutor;
@@ -115,32 +101,24 @@ public final class InternalConfiguration {
this.expressionFactory = initExpressionFactory(config);
this.typeManager = new DefaultTypeManager(config, bootupClasses);
this.multiValueBind = createMultiValueBind(databasePlatform.platform());
this.deployInherit = new DeployInherit(bootupClasses);
this.deployCreateProperties = new DeployCreateProperties(typeManager);
this.deployUtil = new DeployUtil(typeManager, config);
this.serverCachePlugin = initServerCachePlugin();
this.cacheManager = initCacheManager();
final InternalConfigXmlMap xmlMap = initExternalMapping();
this.dtoBeanManager = new DtoBeanManager(typeManager, xmlMap.readDtoMapping());
this.dtoBeanManager = new DtoBeanManager(typeManager);
this.beanDescriptorManager = new BeanDescriptorManager(this);
Map<String, String> asOfTableMapping = beanDescriptorManager.deploy(xmlMap.xmlDeployment());
Map<String, String> draftTableMap = beanDescriptorManager.draftTableMap();
Map<String, String> asOfTableMapping = beanDescriptorManager.deploy();
beanDescriptorManager.scheduleBackgroundTrim();
this.dataTimeZone = initDataTimeZone();
this.binder = getBinder(typeManager, databasePlatform, dataTimeZone);
this.cQueryEngine = new CQueryEngine(config, databasePlatform, binder, asOfTableMapping, draftTableMap);
this.cQueryEngine = new CQueryEngine(config, databasePlatform, binder, asOfTableMapping);
}
public boolean isJacksonCorePresent() {
return jacksonCorePresent;
}
private InternalConfigXmlMap initExternalMapping() {
final List<XmapEbean> xmEbeans = readExternalMapping();
return new InternalConfigXmlMap(xmEbeans, config.getClassLoadConfig().getClassLoader());
}
private <S> S service(Class<S> cls) {
S service = config.getServiceObject(cls);
if (service != null) {
@@ -150,14 +128,6 @@ public final class InternalConfiguration {
}
}
private List<XmapEbean> readExternalMapping() {
final XmapService xmapService = service(XmapService.class);
if (xmapService == null) {
return Collections.emptyList();
}
return xmapService.read(config.getClassLoadConfig().getClassLoader(), config.getMappingLocations());
}
private SpiLogManager initLogManager() {
// allow plugin - i.e. capture executed SQL for testing/asserts
SpiLoggerFactory loggerFactory = service(SpiLoggerFactory.class);
@@ -178,17 +148,6 @@ public final class InternalConfiguration {
return new DefaultExpressionFactory(config.isExpressionEqualsWithNullAsNoop(), nativeIlike);
}
private DocStoreFactory initDocStoreFactory(DocStoreFactory service) {
return service == null ? new NoneDocStoreFactory() : service;
}
/**
* Return the doc store factory.
*/
public DocStoreFactory getDocStoreFactory() {
return docStoreFactory;
}
ClockService getClockService() {
return clockService;
}
@@ -245,22 +204,6 @@ public final class InternalConfiguration {
return plugin((listener != null) ? listener : jacksonCorePresent ? new DefaultChangeLogListener() : null);
}
/**
* Return the ReadAuditLogger implementation to use.
*/
ReadAuditLogger getReadAuditLogger() {
ReadAuditLogger found = bootupClasses.getReadAuditLogger();
return plugin(found != null ? found : jacksonCorePresent ? new DefaultReadAuditLogger() : null);
}
/**
* Return the ReadAuditPrepare implementation to use.
*/
ReadAuditPrepare getReadAuditPrepare() {
ReadAuditPrepare found = bootupClasses.getReadAuditPrepare();
return plugin(found != null ? found : new DefaultReadAuditPrepare());
}
/**
* For 'As Of' queries return the number of bind variables per predicate.
*/
@@ -347,10 +290,6 @@ public final class InternalConfiguration {
return beanDescriptorManager;
}
public DeployInherit getDeployInherit() {
return deployInherit;
}
public DeployCreateProperties getDeployCreateProperties() {
return deployCreateProperties;
}
@@ -372,29 +311,19 @@ public final class InternalConfiguration {
return new GeneratedPropertyFactory(offlineMode, config, bootupClasses.getIdGenerators());
}
/**
* Create the DocStoreIntegration components for the given server.
*/
DocStoreIntegration createDocStoreIntegration(SpiServer server) {
return plugin(docStoreFactory.create(server));
}
/**
* Create the TransactionManager taking into account autoCommit mode.
*/
TransactionManager createTransactionManager(SpiServer server, DocStoreUpdateProcessor indexUpdateProcessor) {
TransactionManager createTransactionManager(SpiServer server) {
TransactionScopeManager scopeManager = createTransactionScopeManager();
boolean notifyL2CacheInForeground = cacheManager.isLocalL2Caching() || config.isNotifyL2CacheInForeground();
TransactionManagerOptions options =
new TransactionManagerOptions(server, notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor,
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
beanDescriptorManager, dataSource(), profileHandler(), logManager,
tableModState, cacheNotify, clockService);
if (config.isDocStoreOnly()) {
return new DocStoreTransactionManager(options);
}
return new TransactionManager(options);
}
@@ -114,7 +114,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return server.databasePlatform().escapeLikeString(value);
}
@Override
public void executeSecondaryQueries(boolean forEach) {
// disable lazy loading leaves loadContext null
if (loadContext != null) {
@@ -148,11 +147,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return loadContext;
}
@Override
public boolean isUseDocStore() {
return query.isUseDocStore();
}
/**
* Run BeanQueryAdapter preQuery() if needed.
*/
@@ -225,7 +219,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
persistenceContext.beginIterate();
}
loadContext = new DLoadContext(this, secondaryQueries);
loadContext.useReferences(Type.ITERATE == query.type());
}
/**
@@ -248,23 +241,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
}
/**
* Return the JsonReadOptions taking into account lazy loading and persistence context.
*/
@Override
public JsonReadOptions createJsonReadOptions() {
persistenceContext = persistenceContext(query, transaction);
if (query.persistenceContext() == null) {
query.setPersistenceContext(persistenceContext);
}
JsonReadOptions jsonRead = new JsonReadOptions();
jsonRead.setPersistenceContext(persistenceContext);
if (!query.isDisableLazyLoading()) {
loadContext = new DLoadContext(this, secondaryQueries);
jsonRead.setLoadContext(loadContext);
}
return jsonRead;
}
/**
* Get the TransactionContext either explicitly set on the query or
@@ -639,17 +615,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
Object cached = beanDescriptor.queryCacheGet(cacheKey);
if (cached != null && isAuditReads() && readAuditQueryType()) {
if (cached instanceof BeanCollection) {
// raw sql can't use L2 cache so normal queries only in here
Collection<T> actualDetails = ((BeanCollection<T>) cached).actualDetails();
List<Object> ids = new ArrayList<>(actualDetails.size());
for (T bean : actualDetails) {
ids.add(beanDescriptor.idForJson(bean));
}
beanDescriptor.readAuditMany(queryPlanKey.partialKey(), "l2-query-cache", ids);
}
}
if (Boolean.FALSE.equals(query.isReadOnly())) {
// return shallow copies if readonly is explicitly set to false
if (cached instanceof BeanCollection) {
@@ -665,24 +630,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return cached;
}
/**
* Return true if the query type contains bean data (not just ids etc) and hence we want to include
* it in read auditing. Return false for row count and find ids queries.
*/
private boolean readAuditQueryType() {
Type type = query.type();
switch (type) {
case BEAN:
case ITERATE:
case LIST:
case SET:
case MAP:
return true;
default:
return false;
}
}
public void putToQueryCache(Object result) {
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.startNanoTime()));
}
@@ -709,15 +656,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return (batchSize > 0) ? batchSize : server.lazyLoadBatchSize();
}
/**
* Return true if read auditing is on for this query request.
* <p>
* This means that read audit is on for this bean type and that query has not explicitly disabled it.
*/
public boolean isAuditReads() {
return beanDescriptor.isReadAuditing() && !query.isDisableReadAudit();
}
/**
* Return the base table alias for this query.
*/
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.core;
import io.ebean.InsertOptions;
import io.ebean.ValuePair;
import io.ebean.annotation.DocStoreMode;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.PreGetterCallback;
@@ -17,21 +16,16 @@ import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.deploy.id.ImportedId;
import io.ebeaninternal.server.persist.*;
import io.ebeaninternal.server.transaction.BeanPersistIdMap;
import io.ebeanservice.docstore.api.DocStoreUpdate;
import io.ebeanservice.docstore.api.DocStoreUpdateContext;
import io.ebeanservice.docstore.api.DocStoreUpdates;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import java.io.IOException;
import java.sql.Statement;
import java.util.*;
/**
* PersistRequest for insert update or delete of a bean.
*/
public final class PersistRequestBean<T> extends PersistRequest implements BeanPersistRequest<T>, DocStoreUpdate, PreGetterCallback, SpiProfileTransactionEvent {
public final class PersistRequestBean<T> extends PersistRequest implements BeanPersistRequest<T>, PreGetterCallback, SpiProfileTransactionEvent {
private final BeanManager<T> beanManager;
private final BeanDescriptor<T> beanDescriptor;
@@ -45,10 +39,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
*/
private final Object parentBean;
private final boolean dirty;
private final boolean publish;
private int flags;
private boolean saveRecurse;
private DocStoreMode docStoreMode;
private final ConcurrencyMode concurrencyMode;
/**
* The unique id used for logging summary.
@@ -139,7 +131,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
this.parentBean = parentBean;
this.controller = beanDescriptor.persistController();
this.type = type;
this.docStoreMode = calcDocStoreMode(transaction, type);
this.flags = flags;
if (Flags.isRecurse(flags)) {
this.persistCascade = t.isPersistCascade();
@@ -155,10 +146,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
}
}
this.concurrencyMode = beanDescriptor.concurrencyMode(intercept);
this.publish = Flags.isPublish(flags);
if (isMarkDraftDirty(publish)) {
beanDescriptor.setDraftDirty(entityBean, true);
}
this.dirty = intercept.isDirty();
}
@@ -187,29 +174,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
profileBase(type.profileEventId, offset, beanDescriptor.name(), flushCount);
}
/**
* Return the document store event that should be used for this request.
* <p>
* Used to check if the Transaction has set the mode to IGNORE when doing large batch inserts that we
* don't want to send to the doc store.
*/
private DocStoreMode calcDocStoreMode(SpiTransaction txn, Type type) {
DocStoreMode txnMode = (txn == null) ? null : txn.docStoreMode();
return beanDescriptor.docStoreMode(type, txnMode);
}
@Override
public boolean isCascade() {
return Flags.isRecurse(flags);
}
/**
* Return true if the draftDirty property should be set to true for this request.
*/
private boolean isMarkDraftDirty(boolean publish) {
return !publish && type != Type.DELETE && beanDescriptor.isDraftable();
}
/**
* Set the transaction from prior persist request.
* Only used when hard deleting draft & associated live beans.
@@ -224,9 +193,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
* Init the transaction and also check for batch on cascade escalation.
*/
public void initTransIfRequiredWithBatchCascade() {
if (createImplicitTransIfRequired()) {
docStoreMode = calcDocStoreMode(transaction, type);
}
createImplicitTransIfRequired();
checkBatchEscalationOnCascade();
}
@@ -427,21 +394,14 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
* Set the cache notify status.
*/
private void setNotifyCache() {
this.notifyCache = beanDescriptor.isCacheNotify(type, publish);
this.notifyCache = beanDescriptor.isCacheNotify(type);
}
/**
* Return true if this change should notify persist listener or doc store (and keep the request).
*/
private boolean isNotifyListeners() {
return isNotifyPersistListener() || isDocStoreNotify();
}
/**
* Return true if this request should update the document store.
*/
private boolean isDocStoreNotify() {
return docStoreMode != DocStoreMode.IGNORE;
return isNotifyPersistListener();
}
private boolean isNotifyPersistListener() {
@@ -470,46 +430,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
}
}
/**
* Process the persist request updating the document store.
*/
@Override
public void docStoreUpdate(DocStoreUpdateContext txn) throws IOException {
switch (type) {
case INSERT:
beanDescriptor.docStoreInsert(idValue, this, txn);
break;
case UPDATE:
case DELETE_SOFT:
beanDescriptor.docStoreUpdate(idValue, this, txn);
break;
case DELETE:
beanDescriptor.docStoreDeleteById(idValue, txn);
break;
default:
throw new IllegalStateException("Invalid type " + type);
}
}
/**
* Add this event to the queue entries in IndexUpdates.
*/
@Override
public void addToQueue(DocStoreUpdates docStoreUpdates) {
switch (type) {
case INSERT:
case UPDATE:
case DELETE_SOFT:
docStoreUpdates.queueIndex(beanDescriptor.docStoreQueueId(), idValue);
break;
case DELETE:
docStoreUpdates.queueDelete(beanDescriptor.docStoreQueueId(), idValue);
break;
default:
throw new IllegalStateException("Invalid type " + type);
}
}
public void addToPersistMap(BeanPersistIdMap beanPersistMap) {
beanPersistMap.add(beanDescriptor, type, idValue);
}
@@ -652,28 +572,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
return beanDescriptor.createRef(beanId(), null);
}
/**
* Return true if the bean type is a Draftable.
*/
public boolean isDraftable() {
return beanDescriptor.isDraftable();
}
/**
* Return true if this request is a hard delete of a draftable bean.
* If this is true Ebean is expected to auto-publish and delete the associated live bean.
*/
public boolean isHardDeleteDraft() {
if (type == Type.DELETE && beanDescriptor.isDraftable() && !beanDescriptor.isDraftableElement()) {
// deleting a top level draftable bean
if (beanDescriptor.isLiveInstance(entityBean)) {
throw new PersistenceException("Explicit Delete is not allowed on a 'live' bean - only draft beans");
}
return true;
}
return false;
}
/**
* Return true if this was a hard/permanent delete request (and should cascade as such).
*/
@@ -681,16 +579,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
return (type == Type.DELETE && beanDescriptor.isSoftDelete());
}
/**
* Checks for @Draftable entity beans with @Draft property that the bean is a 'draft'.
* Save or Update is not allowed to execute using 'live' beans - must use publish().
*/
public void checkDraft() {
if (beanDescriptor.isDraftable() && beanDescriptor.isLiveInstance(entityBean)) {
throw new PersistenceException("Save or update is not allowed on a 'live' bean - only draft beans");
}
}
/**
* Return the parent bean for cascading save with unidirectional relationship.
*/
@@ -876,7 +764,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
setNotifyCache();
boolean isChangeLog = beanDescriptor.isChangeLog();
if (type == Type.UPDATE) {
// get the dirty properties for notify cache & orphanRemoval of vanilla collection detection
// get the dirty properties for update notification to the doc store
dirtyProperties = intercept.dirtyProperties();
}
if (isChangeLog) {
@@ -938,20 +826,19 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
}
private void logSummaryMessage() {
String draft = (beanDescriptor.isDraftable() && !publish) ? " draft[true]" : "";
String name = beanDescriptor.name();
switch (type) {
case INSERT:
transaction.logSummary("Inserted [{0}] [{1}]{2}", name, (idValue == null ? "" : idValue), draft);
transaction.logSummary("Inserted [{0}] [{1}]", name, (idValue == null ? "" : idValue));
break;
case UPDATE:
transaction.logSummary("Updated [{0}] [{1}]{2}", name, idValue , draft);
transaction.logSummary("Updated [{0}] [{1}]", name, idValue);
break;
case DELETE:
transaction.logSummary("Deleted [{0}] [{1}]{2}", name, idValue , draft);
transaction.logSummary("Deleted [{0}] [{1}]", name, idValue);
break;
case DELETE_SOFT:
transaction.logSummary("SoftDelete [{0}] [{1}]{2}", name, idValue , draft);
transaction.logSummary("SoftDelete [{0}] [{1}]", name, idValue);
break;
default:
break;
@@ -989,9 +876,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
private void postInsert() {
// mark all properties as loaded after an insert to support immediate update
beanDescriptor.setAllLoaded(entityBean);
if (!publish) {
beanDescriptor.setDraft(entityBean);
}
if (transaction.isAutoPersistUpdates() && idValue != null) {
// with getGeneratedKeys off we will not have a idValue
beanDescriptor.contextPut(transaction.persistenceContext(), idValue, entityBean);
@@ -1088,32 +972,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
}
}
/**
* For requests that update document store add this event to either the list
* of queue events or list of update events.
*/
public void addDocStoreUpdates(DocStoreUpdates docStoreUpdates) {
if (type == Type.UPDATE) {
beanDescriptor.docStoreUpdateEmbedded(this, docStoreUpdates);
}
switch (docStoreMode) {
case UPDATE: {
docStoreUpdates.addPersist(this);
return;
}
case QUEUE: {
if (type == Type.DELETE) {
docStoreUpdates.queueDelete(beanDescriptor.docStoreQueueId(), idValue);
} else {
docStoreUpdates.queueIndex(beanDescriptor.docStoreQueueId(), idValue);
}
}
break;
default:
break;
}
}
/**
* Determine if all loaded properties should be used for an update.
* <p>
@@ -1139,13 +997,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
return flags;
}
/**
* Return true if this request is a 'publish' action.
*/
public boolean isPublish() {
return publish;
}
/**
* Return the key for an update persist request.
*/
@@ -1162,17 +1013,14 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
key.append('v');
}
}
if (publish) {
key.append('p');
}
return key.toString();
}
/**
* Return the table to update depending if the request is a 'publish' one or normal.
* Return the table to update.
*/
public String updateTable() {
return publish ? beanDescriptor.baseTable() : beanDescriptor.draftTable();
return beanDescriptor.baseTable();
}
/**
@@ -1241,30 +1089,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
return 0;
}
/**
* Persist to the document store now (via buffer, not post commit).
*/
public void docStorePersist() {
idValue = beanDescriptor.getId(entityBean);
if (type == Type.UPDATE) {
dirtyProperties = intercept.dirtyProperties();
}
// processing now so set IGNORE (unlike DB + DocStore processing with post-commit)
docStoreMode = DocStoreMode.IGNORE;
try {
docStoreUpdate(transaction.docStoreTransaction().obtain());
postExecute();
if (type == Type.UPDATE
&& beanDescriptor.isDocStoreEmbeddedInvalidation()
&& transaction.isPersistCascade()) {
// queue embedded/nested updates for later processing
beanDescriptor.docStoreUpdateEmbedded(this, transaction.docStoreTransaction().queue());
}
} catch (IOException e) {
throw new PersistenceException("Error persisting doc store bean", e);
}
}
/**
* Use a common 'now' value across both when created and when updated etc.
*/
@@ -1384,7 +1208,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
* Return the SQL used to fetch the last inserted id value.
*/
public String selectLastInsertedId() {
return beanDescriptor.selectLastInsertedId(publish);
return beanDescriptor.selectLastInsertedId();
}
/**
@@ -78,16 +78,6 @@ public interface Persister {
*/
int executeCallable(CallableSql callable, Transaction t);
/**
* Publish the draft beans matching the given query.
*/
<T> List<T> publish(Query<T> query, Transaction transaction);
/**
* Restore the draft beans back to the matching live beans.
*/
<T> List<T> draftRestore(Query<T> query, Transaction transaction);
/**
* Visit the metrics.
*/
@@ -5,7 +5,6 @@ import io.ebean.Version;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeanservice.docstore.api.DocQueryRequest;
import java.util.Collection;
import java.util.List;
@@ -17,7 +16,7 @@ import java.util.function.Predicate;
/**
* Defines the ORM query request api.
*/
public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequest<T> {
public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T> {
/**
* Return the query.
@@ -178,11 +177,6 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
*/
void markNotQueryOnly();
/**
* Return true if this query is expected to use the doc store.
*/
boolean isUseDocStore();
/**
* Return true if delete by statement is allowed for this type given cascade rules etc.
*/
@@ -9,8 +9,6 @@ import io.ebean.event.*;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.api.CoreLog;
@@ -68,14 +66,10 @@ public class BootupClasses implements Predicate<Class<?>> {
private Class<? extends ChangeLogPrepare> changeLogPrepareClass;
private Class<? extends ChangeLogListener> changeLogListenerClass;
private Class<? extends ChangeLogRegister> changeLogRegisterClass;
private Class<? extends ReadAuditPrepare> readAuditPrepareClass;
private Class<? extends ReadAuditLogger> readAuditLoggerClass;
private ChangeLogPrepare changeLogPrepare;
private ChangeLogListener changeLogListener;
private ChangeLogRegister changeLogRegister;
private ReadAuditPrepare readAuditPrepare;
private ReadAuditLogger readAuditLogger;
public BootupClasses() {
}
@@ -173,19 +167,11 @@ public class BootupClasses implements Predicate<Class<?>> {
}
public void addChangeLogInstances(DatabaseBuilder.Settings config) {
readAuditPrepare = config.getReadAuditPrepare();
readAuditLogger = config.getReadAuditLogger();
changeLogPrepare = config.getChangeLogPrepare();
changeLogListener = config.getChangeLogListener();
changeLogRegister = config.getChangeLogRegister();
// if not already set create the implementations found
// via classpath scanning
if (readAuditPrepare == null && readAuditPrepareClass != null) {
readAuditPrepare = create(readAuditPrepareClass, false);
}
if (readAuditLogger == null && readAuditLoggerClass != null) {
readAuditLogger = create(readAuditLoggerClass, false);
}
if (changeLogPrepare == null && changeLogPrepareClass != null) {
changeLogPrepare = create(changeLogPrepareClass, false);
}
@@ -252,14 +238,6 @@ public class BootupClasses implements Predicate<Class<?>> {
return changeLogRegister;
}
public ReadAuditPrepare getReadAuditPrepare() {
return readAuditPrepare;
}
public ReadAuditLogger getReadAuditLogger() {
return readAuditLogger;
}
public List<IdGenerator> getIdGenerators() {
return createAdd(idGeneratorInstances, idGeneratorCandidates);
}
@@ -424,15 +402,6 @@ public class BootupClasses implements Predicate<Class<?>> {
interesting = true;
}
if (ReadAuditPrepare.class.isAssignableFrom(cls)) {
readAuditPrepareClass = (Class<? extends ReadAuditPrepare>) cls;
interesting = true;
}
if (ReadAuditLogger.class.isAssignableFrom(cls)) {
readAuditLoggerClass = (Class<? extends ReadAuditLogger>) cls;
interesting = true;
}
return interesting;
}
@@ -1,101 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeaninternal.server.query.SqlTreeJoin;
import java.sql.SQLException;
/**
* Helper for BeanPropertyAssocOne imported reference but with inheritance.
*/
final class AssocOneHelpRefInherit extends AssocOneHelp {
private final InheritInfo inherit;
AssocOneHelpRefInherit(BeanPropertyAssocOne<?> property) {
super(property);
this.inherit = property.targetInheritInfo;
}
@Override
void loadIgnore(DbReadContext ctx) {
property.targetIdBinder.loadIgnore(ctx);
ctx.dataReader().incrementPos(1);
}
/**
* Read and set a Reference bean.
*/
@Override
Object read(DbReadContext ctx) throws SQLException {
// read discriminator to determine the type
InheritInfo rowInheritInfo = inherit.readType(ctx);
BeanDescriptor<?> desc;
if (rowInheritInfo != null) {
desc = rowInheritInfo.desc();
} else if (!inherit.hasChildren()) {
desc = inherit.desc();
} else {
// ignore the id property
property.targetIdBinder.loadIgnore(ctx);
return null;
}
Object id = property.targetIdBinder.read(ctx);
if (id == null) {
return null;
}
// check transaction context to see if it already exists
PersistenceContext pc = ctx.persistenceContext();
Object existing = desc.contextGet(pc, id);
if (existing != null) {
return existing;
}
// for inheritance hierarchy create the correct type for this row...
boolean disableLazyLoading = ctx.isDisableLazyLoading();
Object ref = desc.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
if (!disableLazyLoading) {
ctx.registerBeanInherit(property, ((EntityBean) ref)._ebean_getIntercept());
}
return ref;
}
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
// add join to support the discriminator column
String relativePrefix = ctx.relativePrefix(property.name);
ctx.addExtraJoin(new Extra(relativePrefix, joinType));
}
/**
* Extra join to support the discriminator column.
*/
final class Extra implements SqlTreeJoin {
final String relativePrefix;
final SqlJoinType joinType;
Extra(String relativePrefix, SqlJoinType joinType) {
this.relativePrefix = relativePrefix;
this.joinType = joinType;
}
@Override
public void addJoin(DbSqlContext ctx) {
// add join to support the discriminator column *IF* join is not already present
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
}
}
/**
* Append columns for foreign key columns.
*/
@Override
void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!subQuery) {
// add discriminator column
String relativePrefix = ctx.relativePrefix(property.name());
String tableAlias = ctx.tableAlias(relativePrefix);
ctx.appendColumn(tableAlias, property.targetInheritInfo.getDiscriminatorColumn());
}
property.importedId.sqlAppend(ctx);
}
}
@@ -14,13 +14,9 @@ import io.ebean.event.*;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeLogFilter;
import io.ebean.event.changelog.ChangeType;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.event.readaudit.ReadEvent;
import io.ebean.meta.MetaQueryPlan;
import io.ebean.meta.MetricVisitor;
import io.ebean.meta.QueryPlanInit;
import io.ebean.plugin.BeanDocType;
import io.ebean.plugin.BeanType;
import io.ebean.plugin.ExpressionPath;
import io.ebean.plugin.Property;
@@ -45,15 +41,8 @@ import io.ebeaninternal.server.query.*;
import io.ebeaninternal.server.querydefn.DefaultOrmQuery;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
import io.ebeaninternal.server.rawsql.SpiRawSql;
import io.ebeaninternal.util.SortByClause;
import io.ebeaninternal.util.SortByClauseParser;
import io.ebeanservice.docstore.api.DocStoreBeanAdapter;
import io.ebeanservice.docstore.api.DocStoreUpdateContext;
import io.ebeanservice.docstore.api.DocStoreUpdates;
import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import io.ebeanservice.docstore.api.mapping.DocumentMapping;
import jakarta.persistence.PersistenceException;
import java.io.IOException;
@@ -89,8 +78,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final ConcurrentHashMap<String, STreeProperty> dynamicProperty = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Map<String, String>> pathMaps = new ConcurrentHashMap<>();
private final Map<String, SpiRawSql> namedRawSql;
private final Map<String, String> namedQuery;
private final boolean multiValueSupported;
private boolean batchEscalateOnCascadeInsert;
private boolean batchEscalateOnCascadeDelete;
@@ -108,7 +95,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* getGeneratedKeys is not supported.
*/
private final String selectLastInsertedId;
private final String selectLastInsertedIdDraft;
private final boolean autoTunable;
private final ConcurrencyMode concurrencyMode;
private final IndexDefinition[] indexDefinitions;
@@ -120,18 +106,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final TableJoin primaryKeyJoin;
private final BeanProperty softDeleteProperty;
private final boolean softDelete;
private final String draftTable;
private final PartitionMeta partitionMeta;
private final TablespaceMeta tablespaceMeta;
private final String storageEngine;
private final String dbComment;
private final boolean readAuditing;
private final boolean draftable;
private final boolean draftableElement;
private final BeanProperty unmappedJson;
private final BeanProperty tenant;
private final BeanProperty draft;
private final BeanProperty draftDirty;
private final LinkedHashMap<String, BeanProperty> propMap;
/**
* Map of DB column to property path (for nativeSql mapping).
@@ -154,7 +134,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final BeanQueryAdapter queryAdapter;
private final BeanFindController beanFinder;
private final ChangeLogFilter changeLogFilter;
final InheritInfo inheritInfo;
private final boolean abstractType;
private final BeanProperty idProperty;
private final int idPropertyIndex;
@@ -166,10 +145,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* Properties that are initialised in the constructor need to be 'unloaded' to support partial object queries.
*/
private final int[] unloadProperties;
/**
* Properties local to this type (not from a super type).
*/
private final BeanProperty[] propertiesLocal;
/**
* Scalar mutable properties (need to dirty check on update).
*/
@@ -223,13 +198,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final String name;
private final String baseTableAlias;
private final boolean cacheSharableBeans;
private final String docStoreQueueId;
private final BeanDescriptorDraftHelp<T> draftHelp;
private final BeanDescriptorCacheHelp<T> cacheHelp;
private final BeanDescriptorJsonHelp<T> jsonHelp;
private DocStoreBeanAdapter<T> docStoreAdapter;
private DocumentMapping docMapping;
private boolean docStoreEmbeddedInvalidation;
private final String defaultSelectClause;
private SpiEbeanServer ebeanServer;
@@ -245,9 +215,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
this.rootBeanType = PersistenceContextUtil.root(beanType);
this.prototypeEntityBean = createPrototypeEntityBean(beanType);
this.iudMetrics = new BeanIudMetrics(name);
this.namedQuery = deploy.getNamedQuery();
this.namedRawSql = deploy.getNamedRawSql();
this.inheritInfo = deploy.getInheritInfo();
this.beanFinder = deploy.getBeanFinder();
this.persistController = deploy.getPersistController();
this.persistListener = deploy.getPersistListener();
@@ -261,14 +228,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
this.idGeneratedValue = deploy.isIdGeneratedValue();
this.idGenerator = deploy.getIdGenerator();
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
this.selectLastInsertedIdDraft = deploy.getSelectLastInsertedIdDraft();
this.concurrencyMode = deploy.getConcurrencyMode();
this.indexDefinitions = deploy.getIndexDefinitions();
this.readAuditing = deploy.isReadAuditing();
this.draftable = deploy.isDraftable();
this.draftableElement = deploy.isDraftableElement();
this.historySupport = deploy.isHistorySupport();
this.draftTable = deploy.getDraftTable();
this.baseTable = InternString.intern(deploy.getBaseTable());
this.baseTableAsOf = deploy.getBaseTableAsOf();
this.primaryKeyJoin = deploy.getPrimaryKeyJoin();
@@ -290,14 +252,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
this.versionProperty = listHelper.getVersionProperty();
this.unmappedJson = listHelper.getUnmappedJson();
this.tenant = listHelper.getTenant();
this.draft = listHelper.getDraft();
this.draftDirty = listHelper.getDraftDirty();
this.propMap = listHelper.getPropertyMap();
this.propertiesTransient = listHelper.getTransients();
this.propertiesNonTransient = listHelper.getNonTransients();
this.propertiesBaseScalar = listHelper.getBaseScalar();
this.propertiesEmbedded = listHelper.getEmbedded();
this.propertiesLocal = listHelper.getLocal();
this.propertiesMutable = listHelper.getMutable();
this.unidirectional = listHelper.getUnidirectional();
this.orderColumn = listHelper.getOrderColumn();
@@ -320,9 +279,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
this.cacheHelp = new BeanDescriptorCacheHelp<>(this, owner.cacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported);
this.jsonHelp = initJsonHelp();
this.draftHelp = new BeanDescriptorDraftHelp<>(this);
this.docStoreAdapter = owner.createDocStoreBeanAdapter(this, deploy);
this.docStoreQueueId = docStoreAdapter.queueId();
// Check if there are no cascade save associated beans ( subject to change
// in initialiseOther()). Note that if we are in an inheritance hierarchy
// then we also need to check every BeanDescriptors in the InheritInfo as
@@ -482,17 +438,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* as they are used to get the imported and exported properties.
*/
void initialiseId(BeanDescriptorInitContext initContext) {
if (draftable) {
initContext.addDraft(baseTable, draftTable);
}
if (historySupport) {
// add mapping (used to swap out baseTable for asOf queries)
initContext.addHistory(baseTable, baseTableAsOf);
}
if (inheritInfo != null) {
inheritInfo.setDescriptor(this);
}
// initialise just the Id property only
if (idProperty != null) {
idProperty.initialise(initContext);
@@ -503,10 +452,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* Initialise the exported and imported parts for associated properties.
*/
public void initialiseOther(BeanDescriptorInitContext initContext) {
for (BeanPropertyAssocMany<?> many : propertiesManyToMany) {
// register associated draft table for M2M intersection
many.registerDraftIntersectionTable(initContext);
}
if (historySupport) {
// history support on this bean so check all associated intersection tables
// and if they are not excluded register the associated 'with history' table
@@ -607,7 +552,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
}
docStoreEmbeddedInvalidation = docStoreAdapter.hasEmbeddedInvalidation();
}
private void addUniqueColumns(IndexDefinition indexDef) {
@@ -643,11 +587,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
for (BeanPropertyAssocOne<?> one : propertiesOne) {
one.initialisePostTarget();
}
if (inheritInfo != null && !inheritInfo.isRoot()) {
docStoreAdapter = (DocStoreBeanAdapter<T>) inheritInfo.getRoot().desc().docStoreAdapter();
}
docMapping = docStoreAdapter.createDocMapping();
docStoreAdapter.registerPaths();
cacheHelp.deriveNotifyFlags();
}
@@ -675,18 +614,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return type == PersistRequest.Type.INSERT ? batchEscalateOnCascadeInsert : batchEscalateOnCascadeDelete;
}
void initInheritInfo() {
if (inheritInfo != null) {
// need to check every BeanDescriptor in the inheritance hierarchy
if (saveRecurseSkippable) {
saveRecurseSkippable = inheritInfo.isSaveRecurseSkippable();
}
if (deleteRecurseSkippable) {
deleteRecurseSkippable = inheritInfo.isDeleteRecurseSkippable();
}
}
}
public void metricPersistBatch(PersistRequest.Type type, long startNanos, int size) {
iudMetrics.addBatch(type, startNanos, size);
}
@@ -723,20 +650,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
/**
* Return the ReadAuditLogger for logging read audit events.
*/
public ReadAuditLogger readAuditLogger() {
return ebeanServer.readAuditLogger();
}
/**
* Return the ReadAuditPrepare for preparing read audit events prior to logging.
*/
private ReadAuditPrepare readAuditPrepare() {
return ebeanServer.readAuditPrepare();
}
public boolean isChangeLog() {
return changeLogFilter != null;
}
@@ -939,166 +852,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return defaultSelectClause;
}
/**
* Return true if this object is the root level object in its entity
* inheritance.
*/
@Override
public boolean isInheritanceRoot() {
return inheritInfo == null || inheritInfo.isRoot();
}
/**
* Return true if this type maps to a root type of a doc store document (not embedded or ignored).
*/
@Override
public boolean isDocStoreMapped() {
return docStoreAdapter.mapped();
}
/**
* Return true if this bean type has embedded doc store invalidation.
*/
public boolean isDocStoreEmbeddedInvalidation() {
return docStoreEmbeddedInvalidation;
}
/**
* Return the queueId used to uniquely identify this type when queuing an index updateAdd.
*/
@Override
public String docStoreQueueId() {
return docStoreQueueId;
}
@Override
public DocumentMapping docMapping() {
return docMapping;
}
/**
* Return the doc store helper for this bean type.
*/
@Override
public BeanDocType<T> docStore() {
return docStoreAdapter;
}
/**
* Return doc store adapter for internal use for processing persist requests.
*/
public DocStoreBeanAdapter<T> docStoreAdapter() {
return docStoreAdapter;
}
/**
* Build the Document mapping recursively with the given prefix relative to the root of the document.
*/
public void docStoreMapping(final DocMappingBuilder mapping, final String prefix) {
if (prefix != null && idProperty != null) {
// id property not included in the
idProperty.docStoreMapping(mapping, prefix);
}
if (inheritInfo != null) {
String discCol = inheritInfo.getDiscriminatorColumn();
if (Types.VARCHAR == inheritInfo.getDiscriminatorType()) {
mapping.add(new DocPropertyMapping(discCol, DocPropertyType.ENUM));
} else {
mapping.add(new DocPropertyMapping(discCol, DocPropertyType.INTEGER));
}
}
for (BeanProperty prop : propertiesNonTransient) {
prop.docStoreMapping(mapping, prefix);
}
if (inheritInfo != null) {
inheritInfo.visitChildren(inheritInfo1 -> {
for (BeanProperty localProperty : inheritInfo1.localProperties()) {
localProperty.docStoreMapping(mapping, prefix);
}
});
}
}
/**
* Return the root bean type if part of inheritance hierarchy.
*/
@Override
public BeanType<?> root() {
if (inheritInfo != null && !inheritInfo.isRoot()) {
return inheritInfo.getRoot().desc();
}
return this;
}
/**
* Return the full name taking into account inheritance.
*/
public String rootName() {
if (inheritInfo != null && !inheritInfo.isRoot()) {
return inheritInfo.getRoot().desc().name();
}
return name;
}
/**
* Return the named ORM query.
*/
public String namedQuery(String name) {
return namedQuery.get(name);
}
/**
* Return the named RawSql query.
*/
public SpiRawSql namedRawSql(String named) {
return namedRawSql.get(named);
}
/**
* Return the type of DocStoreMode that should occur for this type of persist request
* given the transactions requested mode.
*/
public DocStoreMode docStoreMode(PersistRequest.Type persistType, DocStoreMode txnMode) {
return docStoreAdapter.mode(persistType, txnMode);
}
public void docStoreInsert(Object idValue, PersistRequestBean<T> persistRequest, DocStoreUpdateContext bulkUpdate) throws IOException {
docStoreAdapter.insert(idValue, persistRequest, bulkUpdate);
}
public void docStoreUpdate(Object idValue, PersistRequestBean<T> persistRequest, DocStoreUpdateContext bulkUpdate) throws IOException {
docStoreAdapter.update(idValue, persistRequest, bulkUpdate);
}
/**
* Check if this update invalidates an embedded part of a doc store document.
*/
public void docStoreUpdateEmbedded(PersistRequestBean<T> request, DocStoreUpdates docStoreUpdates) {
docStoreAdapter.updateEmbedded(request, docStoreUpdates);
}
public void docStoreDeleteById(Object idValue, DocStoreUpdateContext txn) throws IOException {
docStoreAdapter.deleteById(idValue, txn);
}
public T publish(T draftBean, T liveBean) {
return draftHelp.publish(draftBean, liveBean);
}
/**
* Reset properties on the draft bean based on @DraftDirty and @DraftReset.
*/
public boolean draftReset(T draftBean) {
return draftHelp.draftReset(draftBean);
}
/**
* Return the draft dirty boolean property or null if there is not one assigned to this bean type.
*/
BeanProperty draftDirty() {
return draftDirty;
}
/**
* Prepare the query for multi-tenancy check for document store only use.
*/
@@ -1109,9 +862,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
tenant.addTenant(query, tenantId);
}
}
if (isDocStoreOnly()) {
query.setUseDocStore(true);
}
}
/**
@@ -1151,11 +901,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
/**
* Return true if the persist request needs to notify the cache.
*/
public boolean isCacheNotify(PersistRequest.Type type, boolean publish) {
if (draftable && !publish) {
// no caching when editing draft beans
return false;
}
public boolean isCacheNotify(PersistRequest.Type type) {
return cacheHelp.isCacheNotify(type);
}
@@ -1372,52 +1118,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
cacheHelp.cacheBeanUpdate(key, changes, updateNaturalKey, version);
}
/**
* Prepare the read audit of a findFutureList() query.
*/
public void readAuditFutureList(SpiQuery<T> spiQuery) {
if (isReadAuditing()) {
ReadEvent event = new ReadEvent(fullName);
// prepare in the foreground thread while we have the user context
// information (query is processed/executed later in bg thread)
readAuditPrepare(event);
spiQuery.setFutureFetchAudit(event);
}
}
/**
* Write a bean read to the read audit log.
*/
public void readAuditBean(String queryKey, String bindLog, Object bean) {
ReadEvent event = new ReadEvent(fullName, queryKey, bindLog, idForJson(bean));
readAuditPrepare(event);
readAuditLogger().auditBean(event);
}
private void readAuditPrepare(ReadEvent event) {
ReadAuditPrepare prepare = readAuditPrepare();
if (prepare != null) {
prepare.prepare(event);
}
}
/**
* Write a many bean read to the read audit log.
*/
public void readAuditMany(String queryKey, String bindLog, List<Object> ids) {
ReadEvent event = new ReadEvent(fullName, queryKey, bindLog, ids);
readAuditPrepare(event);
readAuditLogger().auditMany(event);
}
/**
* Write a futureList many read to the read audit log.
*/
public void readAuditFutureMany(ReadEvent event) {
// this has already been prepared (in foreground thread)
readAuditLogger().auditMany(event);
}
/**
* Return the base table alias. This is always the first letter of the bean name.
*/
@@ -1795,17 +1495,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
if (d != null) {
Object shareableBean = d.getSharableBean();
if (shareableBean != null) {
if (isReadAuditing()) {
readAuditBean("ref", "", shareableBean);
}
return (T) shareableBean;
}
}
}
try {
if (inheritInfo != null && !inheritInfo.isConcrete()) {
return findReferenceBean(id, pc);
}
EntityBean eb = createEntityBean();
id = convertSetId(id, eb);
EntityBeanIntercept ebi = eb._ebean_getIntercept();
@@ -1840,9 +1534,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* Create a non read only reference bean without checking cacheSharableBeans.
*/
public T createReference(Object id, PersistenceContext pc) {
if (inheritInfo != null && !inheritInfo.isConcrete()) {
return findReferenceBean(id, pc);
}
return createRef(id, pc);
}
@@ -1941,17 +1632,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* visible.
*/
public BeanPropertyAssocOne<?> unidirectional() {
BeanDescriptor<?> other = this;
while (true) {
if (other.unidirectional != null) {
return other.unidirectional;
}
if (other.inheritInfo != null && !other.inheritInfo.isRoot()) {
other = other.inheritInfo.getParent().desc();
continue;
}
return null;
}
return unidirectional;
}
/**
@@ -2215,9 +1896,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
if (lazyLoadProperty == -1) {
return false;
}
if (inheritInfo != null) {
return descOf(ebi.owner().getClass()).lazyLoadMany(ebi, lazyLoadProperty, parent);
}
return lazyLoadMany(ebi, lazyLoadProperty, parent);
}
@@ -2245,13 +1923,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return false;
}
/**
* Return the correct BeanDescriptor based on the bean class type.
*/
BeanDescriptor<?> descOf(Class<?> type) {
return inheritInfo.readType(type).desc();
}
/**
* Return a Comparator for local sorting of lists.
*
@@ -2444,13 +2115,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
BeanProperty _findBeanProperty(String propName) {
BeanProperty prop = propMap.get(propName);
if (prop == null) {
if ("_$IdClass$".equals(propName)) {
return idProperty;
} else if (inheritInfo != null) {
// search in sub types...
return inheritInfo.findSubTypeProperty(propName);
}
if (prop == null && "_$IdClass$".equals(propName)) {
return idProperty;
}
return prop;
}
@@ -2484,45 +2150,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return autoTunable;
}
/**
* Returns the Inheritance mapping information. This will be null if this type
* of bean is not involved in any ORM inheritance mapping.
*/
@Override
public InheritInfo inheritInfo() {
return inheritInfo;
}
@Override
public boolean hasInheritance() {
return inheritInfo != null;
}
@Override
public String discColumn() {
return inheritInfo.getDiscriminatorColumn();
}
/**
* Return the discriminator value for this bean type (or null when there is no inheritance).
*/
public String discValue() {
return inheritInfo == null ? null : inheritInfo.getDiscriminatorStringValue();
}
@Override
@SuppressWarnings("unchecked")
public T createBeanUsingDisc(Object discValue) {
return (T) inheritInfo.getType(discValue.toString()).desc().createBean();
}
@Override
public void addInheritanceWhere(Query<?> query) {
if (inheritInfo != null && !inheritInfo.isRoot()) {
query.where().eq(inheritInfo.getDiscriminatorColumn(), inheritInfo.getDiscriminatorValue());
}
}
/**
* Return true if this is an embedded bean.
*/
@@ -2715,8 +2342,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
@Override
public String baseTable(SpiQuery.TemporalMode mode) {
switch (mode) {
case DRAFT:
return draftTable;
case VERSIONS:
return baseTableVersionsBetween;
case AS_OF:
@@ -2726,20 +2351,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
/**
* Return the associated draft table.
*/
public String draftTable() {
return draftTable;
}
/**
* Return true if read auditing is on this entity bean.
*/
public boolean isReadAuditing() {
return readAuditing;
}
@Override
public boolean isSoftDelete() {
return softDelete;
@@ -2771,20 +2382,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
/**
* Return true if this entity type is draftable.
*/
public boolean isDraftable() {
return draftable;
}
/**
* Return true if this entity type is a draftable element (child).
*/
public boolean isDraftableElement() {
return draftableElement;
}
@Override
public Map<String, String> pathMap(String prefix) {
return pathMaps.computeIfAbsent(prefix, s -> {
@@ -2850,28 +2447,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
/**
* Set the draft to true for this entity bean instance.
* This bean is being loaded via asDraft() query.
*/
@Override
public void setDraft(EntityBean entityBean) {
if (draft != null) {
draft.setValue(entityBean, true);
}
}
/**
* Return true if the bean is considered a 'draft' instance (not 'live').
*/
public boolean isDraftInstance(EntityBean entityBean) {
if (draft != null) {
return Boolean.TRUE == draft.getValue(entityBean);
}
// no draft property - so return false
return false;
}
@Override
public boolean isToManyDirty(EntityBean bean) {
final EntityBeanIntercept ebi = bean._ebean_getIntercept();
@@ -2886,39 +2461,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return false;
}
/**
* Return true if the bean is draftable and considered a 'live' instance.
*/
public boolean isLiveInstance(EntityBean entityBean) {
if (draft != null) {
return Boolean.FALSE == draft.getValue(entityBean);
}
// no draft property - so return false
return false;
}
/**
* If there is a @DraftDirty property set it's value on the bean.
*/
public void setDraftDirty(EntityBean entityBean, boolean value) {
if (draftDirty != null) {
// check to see if the dirty property has already
// been set and if so do not set the value
if (!entityBean._ebean_getIntercept().isChangedProperty(draftDirty.propertyIndex())) {
draftDirty.setValueIntercept(entityBean, value);
}
}
}
/**
* Optimise the draft query fetching any draftable element relationships.
*/
public void draftQueryOptimise(Query<T> query) {
// use per query PersistenceContext to ensure fresh beans loaded
query.setPersistenceContextScope(PersistenceContextScope.QUERY);
draftHelp.draftQueryOptimise(query);
}
/**
* Return true if this entity bean has history support.
*/
@@ -2964,8 +2506,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* This is only used with Identity columns and getGeneratedKeys is not
* supported.
*/
public String selectLastInsertedId(boolean publish) {
return publish ? selectLastInsertedId : selectLastInsertedIdDraft;
public String selectLastInsertedId() {
return selectLastInsertedId;
}
/**
@@ -3335,13 +2877,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return propertiesBaseScalar;
}
/**
* Return the properties local to this type for inheritance.
*/
public BeanProperty[] propertiesLocal() {
return propertiesLocal;
}
/**
* Return the properties set as generated values on insert.
*/
@@ -3404,27 +2939,4 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return propertiesUnique;
}
@Override
public List<BeanType<?>> inheritanceChildren() {
if (hasInheritance()) {
return inheritInfo().getChildren()
.stream()
.map(InheritInfo::desc)
.collect(Collectors.toList());
} else {
return Collections.emptyList();
}
}
@Override
public BeanType<?> inheritanceParent() {
return inheritInfo() == null ? null : inheritInfo().getParent().desc();
}
@Override
public void visitAllInheritanceChildren(Consumer<BeanType<?>> visitor) {
if (hasInheritance()) {
inheritInfo().visitChildren(info -> visitor.accept(info.desc()));
}
}
}
@@ -449,44 +449,7 @@ final class BeanDescriptorCacheHelp<T> {
}
void beanPutAll(Collection<EntityBean> beans) {
if (desc.inheritInfo != null) {
Class<?> aClass = theClassOf(beans);
// check if all beans have the same class
for (EntityBean bean : beans) {
if (!bean.getClass().equals(aClass)) {
aClass = null;
break;
}
}
if (aClass == null) {
// there are different bean types in the collection, so we add one by one to the cache
for (EntityBean bean : beans) {
desc.descOf(bean.getClass()).cacheBeanPutDirect(bean);
}
} else {
desc.descOf(aClass).cacheBeanPutAllDirect(beans);
}
} else {
beanCachePutAllDirect(beans);
}
}
private Class<?> theClassOf(Collection<EntityBean> beans) {
if (beans instanceof List) {
return ((List<?>) beans).get(0).getClass();
}
return beans.iterator().next().getClass();
}
/**
* Put a bean into the bean cache.
*/
void beanCachePut(EntityBean bean) {
if (desc.inheritInfo != null) {
desc.descOf(bean.getClass()).cacheBeanPutDirect(bean);
} else {
beanCachePutDirect(bean);
}
beanCachePutAllDirect(beans);
}
void beanCachePutAllDirect(Collection<EntityBean> beans) {
@@ -520,6 +483,13 @@ final class BeanDescriptorCacheHelp<T> {
}
}
/**
* Put a bean into the bean cache.
*/
void beanCachePut(EntityBean bean) {
beanCachePutDirect(bean);
}
/**
* Put the bean into the bean cache.
*/
@@ -594,9 +564,6 @@ final class BeanDescriptorCacheHelp<T> {
if (beanLog.isLoggable(TRACE)) {
beanLog.log(TRACE, " GET {0}({1}) - hit shared bean", cacheName, id);
}
if (desc.isReadAuditing()) {
desc.readAuditBean("l2", "", bean);
}
return (T) bean;
}
}
@@ -607,19 +574,7 @@ final class BeanDescriptorCacheHelp<T> {
* Load the entity bean taking into account inheritance.
*/
private EntityBean loadBean(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
String discValue = data.getDiscValue();
if (discValue == null) {
return loadBeanDirect(id, readOnly, data, context);
} else {
return rootDescriptor(discValue).cacheBeanLoadDirect(id, readOnly, data, context);
}
}
/**
* Return the root BeanDescriptor for inheritance.
*/
private BeanDescriptor<?> rootDescriptor(String discValue) {
return desc.inheritInfo.readType(discValue).desc();
return loadBeanDirect(id, readOnly, data, context);
}
/**
@@ -648,9 +603,6 @@ final class BeanDescriptorCacheHelp<T> {
}
CachedBeanDataToBean.load(desc, bean, data, context);
if (desc.isReadAuditing()) {
desc.readAuditBean("l2", "", bean);
}
return bean;
}
@@ -658,12 +610,7 @@ final class BeanDescriptorCacheHelp<T> {
* Load the embedded bean checking for inheritance.
*/
EntityBean embeddedBeanLoad(CachedBeanData data, PersistenceContext context) {
String discValue = data.getDiscValue();
if (discValue == null) {
return embeddedBeanLoadDirect(data, context);
} else {
return rootDescriptor(discValue).cacheEmbeddedBeanLoadDirect(data, context);
}
return embeddedBeanLoadDirect(data, context);
}
/**
@@ -1,99 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.bean.EntityBean;
import java.util.ArrayList;
import java.util.List;
/**
* Helper for BeanDescriptor that manages draft entity beans.
*
* @param <T> The entity bean type
*/
final class BeanDescriptorDraftHelp<T> {
private final BeanDescriptor<T> desc;
private final BeanProperty draftDirty;
private final BeanProperty[] resetProperties;
BeanDescriptorDraftHelp(BeanDescriptor<T> desc) {
this.desc = desc;
this.draftDirty = desc.draftDirty();
this.resetProperties = resetProperties();
}
/**
* Return the properties that are reset on draft beans after publish.
*/
private BeanProperty[] resetProperties() {
List<BeanProperty> list = new ArrayList<>();
for (BeanProperty prop : desc.propertiesNonMany()) {
if (prop.isDraftReset()) {
list.add(prop);
}
}
return list.toArray(new BeanProperty[0]);
}
/**
* Set the value of all the 'reset properties' to null on the draft bean.
*/
boolean draftReset(T draftBean) {
EntityBean draftEntityBean = (EntityBean) draftBean;
if (draftDirty != null) {
// set @DraftDirty property to false
draftDirty.setValueIntercept(draftEntityBean, false);
}
// set to null on all @DraftReset properties
for (BeanProperty resetProperty : resetProperties) {
resetProperty.setValueIntercept(draftEntityBean, null);
}
// return true if the bean is dirty (and should be persisted)
return draftEntityBean._ebean_getIntercept().isDirty();
}
/**
* Transfer the values from the draftBean to the liveBean.
* <p>
* This will recursive transfer values to all @DraftableElement properties.
* </p>
*/
@SuppressWarnings("unchecked")
public T publish(T draftBean, T liveBean) {
if (liveBean == null) {
liveBean = (T) desc.createEntityBean();
}
EntityBean draft = (EntityBean) draftBean;
EntityBean live = (EntityBean) liveBean;
BeanProperty idProperty = desc.idProperty();
if (idProperty != null) {
idProperty.publish(draft, live);
}
for (BeanProperty prop : desc.propertiesNonMany()) {
prop.publish(draft, live);
}
for (BeanPropertyAssocMany<?> many : desc.propertiesMany()) {
if (many.targetDescriptor().isDraftable()) {
many.publishMany(draft, live);
}
}
return liveBean;
}
/**
* Fetch draftable element relationships.
*/
void draftQueryOptimise(Query<T> query) {
for (BeanPropertyAssocOne<?> anOne : desc.propertiesOne()) {
if (anOne.targetDescriptor().isDraftableElement()) {
query.fetch(anOne.name());
}
}
for (BeanPropertyAssocMany<?> aMany : desc.propertiesMany()) {
if (aMany.targetDescriptor().isDraftableElement()) {
query.fetch(aMany.name());
}
}
}
}
@@ -5,20 +5,14 @@ import java.util.Map;
class BeanDescriptorInitContext {
private final Map<String, String> withHistoryTables;
private final Map<String, String> draftTables;
private final String asOfViewSuffix;
private String embeddedPrefix;
BeanDescriptorInitContext(Map<String, String> withHistoryTables, Map<String, String> draftTables, String asOfViewSuffix) {
BeanDescriptorInitContext(Map<String, String> withHistoryTables, String asOfViewSuffix) {
this.withHistoryTables = withHistoryTables;
this.draftTables = draftTables;
this.asOfViewSuffix = asOfViewSuffix;
}
void addDraft(String baseTable, String draftTable) {
draftTables.put(baseTable, draftTable);
}
void addHistory(String baseTable, String baseTableAsOf) {
withHistoryTables.put(baseTable, baseTableAsOf);
}
@@ -27,10 +21,6 @@ class BeanDescriptorInitContext {
withHistoryTables.put(intersectionTableName, intersectionTableName + asOfViewSuffix);
}
void addDraftIntersection(String intersectionPublishTable, String intersectionDraftTable) {
draftTables.put(intersectionPublishTable, intersectionDraftTable);
}
public void setEmbeddedPrefix(String embeddedPrefix) {
this.embeddedPrefix = embeddedPrefix;
}
@@ -19,24 +19,14 @@ import static io.ebeaninternal.server.persist.DmlUtil.isNullOrZero;
final class BeanDescriptorJsonHelp<T> {
private final BeanDescriptor<T> desc;
private final InheritInfo inheritInfo;
BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
this.desc = desc;
this.inheritInfo = desc.inheritInfo;
}
void jsonWrite(SpiJsonWriter writeJson, EntityBean bean, String key) throws IOException {
writeJson.writeStartObject(key);
if (inheritInfo == null) {
jsonWriteProperties(writeJson, bean);
} else {
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
String discValue = localInheritInfo.getDiscriminatorStringValue();
String discColumn = localInheritInfo.getDiscriminatorColumn();
writeJson.gen().writeStringField(discColumn, discValue);
localInheritInfo.desc().jsonWriteProperties(writeJson, bean);
}
jsonWriteProperties(writeJson, bean);
writeJson.writeEndObject();
}
@@ -45,11 +35,7 @@ final class BeanDescriptorJsonHelp<T> {
}
void jsonWriteDirty(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
if (inheritInfo == null) {
jsonWriteDirtyProperties(writeJson, bean, dirtyProps);
} else {
desc.descOf(bean.getClass()).jsonWriteDirtyProperties(writeJson, bean, dirtyProps);
}
jsonWriteDirtyProperties(writeJson, bean, dirtyProps);
}
void jsonWriteDirtyProperties(SpiJsonWriter writeJson, EntityBean bean, boolean[] dirtyProps) throws IOException {
@@ -80,31 +66,7 @@ final class BeanDescriptorJsonHelp<T> {
throw new JsonParseException(parser, "Unexpected token " + token + " - expecting start_object", parser.getCurrentLocation());
}
}
if (desc.inheritInfo == null || !withInheritance) {
return jsonReadObject(jsonRead, path, target);
}
ObjectNode node = jsonRead.mapper().readTree(parser);
if (node.isNull()) {
return null;
}
JsonParser newParser = node.traverse();
SpiJsonReader newReader = jsonRead.forJson(newParser);
// check for the discriminator value to determine the correct sub type
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
JsonNode discNode = node.get(discColumn);
if (discNode == null || discNode.isNull()) {
if (!desc.isAbstractType()) {
return desc.jsonReadObject(newReader, path, target);
}
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
throw new JsonParseException(newParser, msg, parser.getCurrentLocation());
}
BeanDescriptor<T> inheritDesc = (BeanDescriptor<T>) inheritInfo.readType(discNode.asText()).desc();
return inheritDesc.jsonReadObject(newReader, path, target);
return jsonReadObject(jsonRead, path, target);
}
private T jsonReadObject(SpiJsonReader readJson, String path, T target) throws IOException {
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.deploy;
import io.ebean.BackgroundExecutor;
import io.ebean.DatabaseBuilder;
import io.ebean.Model;
import io.ebean.RawSqlBuilder;
import io.ebean.annotation.ConstraintMode;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean;
@@ -36,12 +35,6 @@ import io.ebeaninternal.server.properties.BeanPropertiesReader;
import io.ebeaninternal.server.properties.BeanPropertyAccess;
import io.ebeaninternal.server.properties.EnhanceBeanPropertyAccess;
import io.ebeaninternal.server.type.TypeManager;
import io.ebeaninternal.xmapping.api.XmapEbean;
import io.ebeaninternal.xmapping.api.XmapEntity;
import io.ebeaninternal.xmapping.api.XmapNamedQuery;
import io.ebeaninternal.xmapping.api.XmapRawSql;
import io.ebeanservice.docstore.api.DocStoreBeanAdapter;
import io.ebeanservice.docstore.api.DocStoreFactory;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PersistenceException;
@@ -67,7 +60,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private final ReadAnnotations readAnnotations;
private final TransientProperties transientProperties;
private final DeployInherit deplyInherit;
private final BeanPropertyAccess beanPropertyAccess = new EnhanceBeanPropertyAccess();
private final DeployUtil deployUtil;
private final PersistControllerManager persistControllerManager;
@@ -83,7 +75,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private final ChangeLogListener changeLogListener;
private final ChangeLogRegister changeLogRegister;
private final ChangeLogPrepare changeLogPrepare;
private final DocStoreFactory docStoreFactory;
private final MultiValueBind multiValueBind;
private final TypeManager typeManager;
private final BootupClasses bootupClasses;
@@ -91,7 +82,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private final List<BeanDescriptor<?>> elementDescriptors = new ArrayList<>();
private final Map<Class<?>, BeanTable> beanTableMap = new HashMap<>();
private final Map<String, BeanDescriptor<?>> descMap = new HashMap<>();
private final Map<String, BeanDescriptor<?>> descQueueMap = new HashMap<>();
private final Map<String, BeanManager<?>> beanManagerMap = new HashMap<>();
private final Map<String, List<BeanDescriptor<?>>> tableToDescMap = new HashMap<>();
private final Map<String, List<BeanDescriptor<?>>> tableToViewDescMap = new HashMap<>();
@@ -113,10 +103,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
* Map of base tables to 'with history views' used to support 'as of' queries.
*/
private final Map<String, String> asOfTableMap = new HashMap<>();
/**
* Map of base tables to 'draft' tables.
*/
private final Map<String, String> draftTableMap = new HashMap<>();
// temporary collections used during startup and then cleared
private Map<Class<?>, DeployBeanInfo<?>> deployInfoMap = new HashMap<>();
@@ -130,7 +116,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
this.config = config.getConfig();
this.serverName = InternString.intern(this.config.getName());
this.cacheManager = config.getCacheManager();
this.docStoreFactory = config.getDocStoreFactory();
this.backgroundExecutor = config.getBackgroundExecutor();
this.dataSource = this.config.getDataSource();
this.encryptKeyManager = this.config.getEncryptKeyManager();
@@ -145,7 +130,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
this.createProperties = config.getDeployCreateProperties();
this.namingConvention = this.config.getNamingConvention();
this.dbIdentity = config.getDatabasePlatform().dbIdentity();
this.deplyInherit = config.getDeployInherit();
this.deployUtil = config.getDeployUtil();
this.typeManager = deployUtil.typeManager();
this.beanManagerFactory = new BeanManagerFactory(config.getDatabasePlatform());
@@ -235,15 +219,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
return config;
}
@Override
public <T> DocStoreBeanAdapter<T> createDocStoreBeanAdapter(BeanDescriptor<T> descriptor, DeployBeanDescriptor<T> deploy) {
return docStoreFactory.createAdapter(descriptor, deploy);
}
public BeanDescriptor<?> descriptorByQueueId(String queueId) {
return descQueueMap.get(queueId);
}
@Override
public SpiBeanType beanType(Class<?> entityType) {
return descriptor(entityType);
@@ -289,24 +264,15 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
return idBinderFactory.createIdBinder(idProperty);
}
/**
* Return the map of base tables to draft tables.
*/
public Map<String, String> draftTableMap() {
return draftTableMap;
}
/**
* Deploy returning the asOfTableMap (which is required by the SQL builders).
*/
public Map<String, String> deploy(List<XmapEbean> mappings) {
public Map<String, String> deploy() {
try {
createListeners();
readEntityDeploymentInitial();
readXmlMapping(mappings);
readEntityBeanTable();
readEntityDeploymentAssociations();
readInheritedIdGenerators();
// creates the BeanDescriptors
readEntityRelationships();
List<BeanDescriptor<?>> list = new ArrayList<>(descMap.values());
@@ -330,56 +296,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
}
}
private void readXmlMapping(List<XmapEbean> mappings) {
if (mappings != null) {
ClassLoader classLoader = config.getClassLoadConfig().getClassLoader();
for (XmapEbean mapping : mappings) {
List<XmapEntity> entityDeploy = mapping.getEntity();
for (XmapEntity deploy : entityDeploy) {
readEntityMapping(classLoader, deploy);
}
}
}
}
private void readEntityMapping(ClassLoader classLoader, XmapEntity entityDeploy) {
String entityClassName = entityDeploy.getClazz();
Class<?> entityClass;
try {
entityClass = Class.forName(entityClassName, false, classLoader);
} catch (Exception e) {
log.log(ERROR, "Could not load entity bean class " + entityClassName + " for ebean.xml entry");
return;
}
DeployBeanInfo<?> info = deployInfoMap.get(entityClass);
if (info == null) {
log.log(ERROR, "No entity bean for ebean.xml entry " + entityClassName);
} else {
for (XmapRawSql sql : entityDeploy.getRawSql()) {
RawSqlBuilder builder;
try {
builder = RawSqlBuilder.parse(sql.getQuery());
} catch (RuntimeException e) {
builder = RawSqlBuilder.unparsed(sql.getQuery());
}
for (Map.Entry<String, String> columnMapping : sql.getColumnMapping().entrySet()) {
builder.columnMapping(columnMapping.getKey(), columnMapping.getValue());
}
for (Map.Entry<String, String> aliasMapping : sql.getAliasMapping().entrySet()) {
builder.tableAliasMapping(aliasMapping.getKey(), aliasMapping.getValue());
}
info.addRawSql(sql.getName(), builder.create());
}
for (XmapNamedQuery namedQuery : entityDeploy.getNamedQuery()) {
info.addNamedQuery(namedQuery.getName(), namedQuery.getQuery());
}
}
}
/**
* Return the Encrypt key given the table and column name.
*/
@@ -487,7 +403,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
// now that all the BeanDescriptors are in their map
// we can initialise them which sorts out circular
// dependencies for OneToMany and ManyToOne etc
BeanDescriptorInitContext initContext = new BeanDescriptorInitContext(asOfTableMap, draftTableMap, asOfViewSuffix);
BeanDescriptorInitContext initContext = new BeanDescriptorInitContext(asOfTableMap, asOfViewSuffix);
// PASS 1:
// initialise the ID properties of all the beans
@@ -497,12 +413,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
d.initialiseId(initContext);
}
// PASS 2:
// now initialise all the inherit info
for (BeanDescriptor<?> d : descMap.values()) {
d.initInheritInfo();
}
// PASS 2: Was to initialise all the inherit info
// PASS 3:
// now initialise all the associated properties
for (BeanDescriptor<?> d : descMap.values()) {
@@ -634,9 +545,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private void registerDescriptor(DeployBeanInfo<?> info) {
BeanDescriptor<?> desc = new BeanDescriptor<>(this, info.getDescriptor());
descMap.put(desc.type().getName(), desc);
if (desc.isDocStoreMapped()) {
descQueueMap.put(desc.docStoreQueueId(), desc);
}
for (BeanPropertyAssocMany<?> many : desc.propertiesMany()) {
if (many.isElementCollection()) {
elementDescriptors.add(many.elementDescriptor());
@@ -706,20 +614,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
}
}
private void readInheritedIdGenerators() {
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
DeployBeanDescriptor<?> descriptor = info.getDescriptor();
InheritInfo inheritInfo = descriptor.getInheritInfo();
if (inheritInfo != null && !inheritInfo.isRoot()) {
DeployBeanInfo<?> rootBeanInfo = deployInfoMap.get(inheritInfo.getRoot().getType());
PlatformIdGenerator rootIdGen = rootBeanInfo.getDescriptor().getIdGenerator();
if (rootIdGen != null) {
descriptor.setIdGenerator(rootIdGen);
}
}
}
}
/**
* Create the BeanTable from the deployment information gathered so far.
*/
@@ -742,9 +636,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
secondaryPropsJoins(info);
}
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
setInheritanceInfo(info);
}
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
if (!info.isEmbedded()) {
registerDescriptor(info);
@@ -752,28 +643,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
}
}
/**
* Sets the inheritance info.
*/
private void setInheritanceInfo(DeployBeanInfo<?> info) {
for (DeployBeanPropertyAssocOne<?> oneProp : info.getDescriptor().propertiesAssocOne()) {
if (!oneProp.isTransient()) {
DeployBeanInfo<?> assoc = deployInfoMap.get(oneProp.getTargetType());
if (assoc != null) {
oneProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
}
}
}
for (DeployBeanPropertyAssocMany<?> manyProp : info.getDescriptor().propertiesAssocMany()) {
if (!manyProp.isTransient()) {
DeployBeanInfo<?> assoc = deployInfoMap.get(manyProp.getTargetType());
if (assoc != null) {
manyProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
}
}
}
}
private void secondaryPropsJoins(DeployBeanInfo<?> info) {
DeployBeanDescriptor<?> descriptor = info.getDescriptor();
for (DeployBeanProperty prop : descriptor.propertiesBase()) {
@@ -907,13 +776,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
orderProperty.setDbUpdateable(orderColumn.isUpdatable());
orderProperty.setDbRead(true);
orderProperty.setOwningType(targetDesc.getBeanType());
final InheritInfo targetInheritInfo = targetDesc.getInheritInfo();
if (targetInheritInfo != null) {
for (InheritInfo child : targetInheritInfo.getChildren()) {
final DeployBeanDescriptor<?> childDescriptor = deployInfoMap.get(child.getType()).getDescriptor();
childDescriptor.setOrderColumn(orderProperty);
}
}
targetDesc.setOrderColumn(orderProperty);
}
@@ -1029,13 +891,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
// skip mapping check
return;
}
DeployBeanDescriptor<?> targetDesc = targetDescriptor(prop);
if (targetDesc.isDraftableElement()) {
// automatically turning on orphan removal and CascadeType.ALL
prop.setModifyListenMode(BeanCollection.ModifyListenMode.REMOVALS);
prop.getCascadeInfo().setSaveDelete(true, true);
}
if (prop.hasOrderColumn()) {
makeOrderColumn(prop);
}
@@ -1061,6 +916,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
String mappedBy = prop.getMappedBy();
// get the mappedBy property
DeployBeanDescriptor<?> targetDesc = targetDescriptor(prop);
DeployBeanPropertyAssocOne<?> mappedAssocOne = mappedManyToOne(prop, targetDesc, mappedBy);
DeployTableJoin tableJoin = prop.getTableJoin();
if (!tableJoin.hasJoinColumns()) {
@@ -1102,9 +958,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
// get the bean descriptor that holds the mappedBy property
String mappedBy = prop.getMappedBy();
if (mappedBy == null) {
if (targetDescriptor(prop).isDraftable()) {
prop.setIntersectionDraftTable();
}
return;
}
@@ -1129,10 +982,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
DeployTableJoin inverseJoin = new DeployTableJoin();
mappedIntJoin.copyTo(inverseJoin, false, intTableName);
prop.setInverseJoin(inverseJoin);
if (targetDesc.isDraftable()) {
prop.setIntersectionDraftTable();
}
}
private DeployBeanPropertyAssocMany<?> mappedManyToMany(DeployBeanPropertyAssocMany<?> prop, String mappedBy, DeployBeanDescriptor<?> targetDesc) {
@@ -1174,9 +1023,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
beanLifecycleAdapterFactory.addLifecycleMethods(desc);
// set bean controller, finder and listener
setBeanControllerFinderListener(desc);
deplyInherit.process(desc);
desc.checkInheritanceMapping();
createProperties.createProperties(desc);
DeployBeanInfo<T> info = new DeployBeanInfo<>(deployUtil, desc);
readAnnotations.readInitial(info);
@@ -1249,8 +1095,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
if (identityMode.isIdentity()) {
// used when getGeneratedKeys is not supported (SQL Server 2000, SAP Hana)
String selectLastInsertedId = dbIdentity.getSelectLastInsertedId(desc.getBaseTable());
String selectLastInsertedIdDraft = (!desc.isDraftable()) ? selectLastInsertedId : dbIdentity.getSelectLastInsertedId(desc.getDraftTable());
desc.setSelectLastInsertedId(selectLastInsertedId, selectLastInsertedIdDraft);
desc.setSelectLastInsertedId(selectLastInsertedId);
return;
}
@@ -7,7 +7,6 @@ import io.ebean.core.type.ScalarType;
import io.ebeaninternal.server.cache.SpiCacheManager;
import io.ebeaninternal.server.deploy.id.IdBinder;
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import io.ebeanservice.docstore.api.DocStoreBeanAdapter;
/**
* Provides a method to find a BeanDescriptor.
@@ -57,11 +56,6 @@ public interface BeanDescriptorMap {
*/
IdBinder createIdBinder(BeanProperty id);
/**
* Create a doc store specific adapter for this bean type.
*/
<T> DocStoreBeanAdapter<T> createDocStoreBeanAdapter(BeanDescriptor<T> descriptor, DeployBeanDescriptor<T> deploy);
/**
* Return the scalarType for the given JDBC type.
*/
@@ -37,10 +37,6 @@ import io.ebeaninternal.server.query.SqlBeanLoad;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeaninternal.server.type.*;
import io.ebeaninternal.util.ValueUtil;
import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
import io.ebeanservice.docstore.api.support.DocStructure;
import jakarta.persistence.PersistenceException;
import java.io.DataInput;
@@ -144,7 +140,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
@SuppressWarnings("rawtypes")
final ScalarType scalarType;
private final DocPropertyOptions docOptions;
/**
* The length or precision for DB column.
*/
@@ -173,10 +168,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
final boolean jsonDeserialize;
private final boolean unmappedJson;
private final boolean tenantId;
private final boolean draft;
private final boolean draftOnly;
private final boolean draftDirty;
private final boolean draftReset;
private final boolean softDelete;
private final String softDeleteDbSet;
private final String softDeleteDbPredicate;
@@ -203,10 +194,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.excludedFromHistory = deploy.isExcludedFromHistory();
this.unmappedJson = deploy.isUnmappedJson();
this.tenantId = deploy.isTenantId();
this.draft = deploy.isDraft();
this.draftDirty = deploy.isDraftDirty();
this.draftOnly = deploy.isDraftOnly();
this.draftReset = deploy.isDraftReset();
this.secondaryTable = deploy.isSecondaryTable();
if (secondaryTable) {
this.secondaryTableJoin = new TableJoin(deploy.getSecondaryTableJoin());
@@ -245,7 +232,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.lob = isLobType(dbType);
this.propertyType = deploy.getPropertyType();
this.field = deploy.getField();
this.docOptions = deploy.getDocPropertyOptions();
this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), false, null);
this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), dbEncrypted, dbColumn);
this.elPrefix = deploy.getElPrefix();
@@ -299,10 +285,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.aggregation = null;
this.excludedFromHistory = source.excludedFromHistory;
this.tenantId = source.tenantId;
this.draft = source.draft;
this.draftDirty = source.draftDirty;
this.draftOnly = source.draftOnly;
this.draftReset = source.draftReset;
this.softDelete = source.softDelete;
this.softDeleteDbSet = source.softDeleteDbSet;
this.softDeleteDbPredicate = source.softDeleteDbPredicate;
@@ -341,7 +323,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.lob = isLobType(dbType);
this.propertyType = source.type();
this.field = source.field();
this.docOptions = source.docOptions;
this.unmappedJson = source.unmappedJson;
this.elPrefix = override.replace(source.elPrefix, source.dbColumn);
this.elPlaceHolder = override.replace(source.elPlaceHolder, source.dbColumn);
@@ -487,7 +468,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
ctx.appendFormulaSelect(aggregation);
} else if (formula) {
ctx.appendFormulaSelect(sqlFormulaSelect);
} else if (!isTransient && !ignoreDraftOnlyProperty(ctx.isDraftQuery())) {
} else if (!isTransient) {
if (secondaryTableJoin != null) {
ctx.pushTableAlias(ctx.relativePrefix(secondaryTableJoinPrefix));
}
@@ -606,17 +587,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
return local;
}
/**
* Copy/set the property value from the draft bean to the live bean.
*/
public void publish(EntityBean draftBean, EntityBean liveBean) {
if (!version && !draftOnly) {
// set property value from draft to live
Object value = getValueIntercept(draftBean);
setValueIntercept(liveBean, value);
}
}
/**
* Return the DB literal expression to set the deleted state to true.
*/
@@ -1106,16 +1076,8 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
/**
* Return true if this property is loadable from a resultSet.
*/
public boolean isLoadProperty(boolean draftQuery) {
return !ignoreDraftOnlyProperty(draftQuery) && (!isTransient || formula);
}
/**
* Return true if this is a draftOnly property on a non-asDraft query and as such this
* property should not be included in a sql query.
*/
private boolean ignoreDraftOnlyProperty(boolean draftQuery) {
return draftOnly && !draftQuery;
public boolean isLoadProperty() {
return !isTransient || formula;
}
/**
@@ -1264,36 +1226,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
return tenantId;
}
/**
* Return true if this property only exists on the draft table.
*/
public boolean isDraftOnly() {
return draftOnly;
}
/**
* Return true if this property is a boolean flag on a draftable bean
* indicating if the instance is a draft or live bean.
*/
public boolean isDraft() {
return draft;
}
/**
* Return true if this property is a boolean flag only on the draft table
* indicating that when the draft is different from the published row.
*/
public boolean isDraftDirty() {
return draftDirty;
}
/**
* Return true if this property is reset/cleared on publish (on the draft bean).
*/
boolean isDraftReset() {
return draftReset;
}
/**
* Return true if this property is the soft delete property.
*/
@@ -1360,15 +1292,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
return name;
}
/**
* Append this property to the document store based on includeByDefault setting.
*/
public void docStoreInclude(boolean includeByDefault, DocStructure docStructure) {
if (includeByDefault) {
docStructure.addProperty(name);
}
}
public boolean isJsonSerialize() {
return jsonSerialize;
}
@@ -1478,24 +1401,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
}
}
/**
* Add to the document mapping if this property is included for this index.
*/
public void docStoreMapping(DocMappingBuilder mapping, String prefix) {
if (mapping.includesProperty(prefix, name)) {
DocPropertyType type = scalarType.docType();
DocPropertyOptions options = docOptions.copy();
if (isKeywordType(type, options)) {
type = DocPropertyType.KEYWORD;
}
mapping.add(new DocPropertyMapping(name, type, options));
}
}
private boolean isKeywordType(DocPropertyType type, DocPropertyOptions docOptions) {
return type == DocPropertyType.TEXT && (docOptions.isCode() || id || discriminator);
}
public void merge(EntityBean bean, EntityBean existing) {
// do nothing unless Many property
}
@@ -4,9 +4,6 @@ import io.ebean.Query;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.DocPropertyType;
import io.ebean.text.PathProperties;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
@@ -24,9 +21,6 @@ import io.ebeaninternal.server.query.STreePropertyAssoc;
import io.ebeaninternal.server.query.STreeType;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeaninternal.server.querydefn.DefaultOrmQuery;
import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import io.ebeanservice.docstore.api.support.DocStructure;
import jakarta.persistence.PersistenceException;
import java.util.ArrayList;
@@ -45,7 +39,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
*/
BeanDescriptor<T> targetDescriptor;
IdBinder targetIdBinder;
InheritInfo targetInheritInfo;
String targetIdProperty;
/**
* Derived list of exported property and matching foreignKey
@@ -69,7 +62,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
*/
final BeanTable beanTable;
final String mappedBy;
private final String docStoreDoc;
private final String extraWhere;
private final int fetchPreference;
private boolean saveRecurseSkippable;
@@ -83,7 +75,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
this.extraWhere = InternString.intern(deploy.getExtraWhere());
this.beanTable = deploy.getBeanTable();
this.mappedBy = InternString.intern(deploy.getMappedBy());
this.docStoreDoc = deploy.getDocStoreDoc();
this.tableJoin = new TableJoin(deploy.getTableJoin());
this.targetType = deploy.getTargetType();
this.cascadeInfo = deploy.getCascadeInfo();
@@ -100,7 +91,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
extraWhere = source.extraWhere;
beanTable = source.beanTable;
mappedBy = source.mappedBy;
docStoreDoc = source.docStoreDoc;
targetType = source.targetType;
cascadeInfo = source.cascadeInfo;
fetchPreference = source.fetchPreference;
@@ -121,7 +111,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
targetDescriptor = descriptor.descriptor(targetType);
if (!isTransient) {
targetIdBinder = targetDescriptor.idBinder();
targetInheritInfo = targetDescriptor.inheritInfo();
saveRecurseSkippable = targetDescriptor.isSaveRecurseSkippable();
if (!targetIdBinder.isComplexId()) {
targetIdProperty = targetIdBinder.idSelect();
@@ -310,59 +299,6 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
return extraWhere;
}
/**
* Return the elastic search doc for this embedded property.
*/
private String docStoreDoc() {
return docStoreDoc;
}
/**
* Determine if and how the associated bean is included in the doc store document.
*/
@Override
public void docStoreInclude(boolean includeByDefault, DocStructure docStructure) {
String embeddedDoc = docStoreDoc();
if (embeddedDoc == null) {
// not annotated so use include by default
// which is *ToOne included and *ToMany excluded
if (includeByDefault) {
docStoreIncludeByDefault(docStructure.doc());
}
} else {
// explicitly annotated to be included
if (embeddedDoc.isEmpty()) {
embeddedDoc = "*";
}
// add in a nested way
PathProperties embDoc = PathProperties.parse(embeddedDoc);
docStructure.addNested(name, embDoc);
}
}
/**
* Include the property in the document store by default.
*/
void docStoreIncludeByDefault(PathProperties pathProps) {
pathProps.addToPath(null, name);
}
@Override
public void docStoreMapping(DocMappingBuilder mapping, String prefix) {
if (mapping.includesPath(prefix, name)) {
String fullName = SplitName.add(prefix, name);
DocPropertyType type = isMany() ? DocPropertyType.LIST : DocPropertyType.OBJECT;
DocPropertyMapping nested = new DocPropertyMapping(name, type);
mapping.push(nested);
targetDescriptor.docStoreMapping(mapping, fullName);
mapping.pop();
if (!nested.children().isEmpty()) {
mapping.add(nested);
}
}
}
/**
* Return true if this association is updateable.
*/
@@ -41,8 +41,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
* Join for manyToMany intersection table.
*/
private final TableJoin intersectionJoin;
private final String intersectionPublishTable;
private final String intersectionDraftTable;
private final boolean orphanRemoval;
private IntersectionTable intersectionTable;
/**
@@ -102,13 +100,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
this.mapKey = deploy.getMapKey();
this.fetchOrderBy = deploy.getFetchOrderBy();
this.intersectionJoin = deploy.createIntersectionTableJoin();
if (intersectionJoin != null) {
this.intersectionPublishTable = intersectionJoin.getTable();
this.intersectionDraftTable = deploy.getIntersectionDraftTable();
} else {
this.intersectionPublishTable = null;
this.intersectionDraftTable = null;
}
this.inverseJoin = deploy.createInverseTableJoin();
this.modifyListenMode = deploy.getModifyListenMode();
this.jsonHelp = descriptor.isJacksonCorePresent() ? new BeanPropertyAssocManyJsonHelp(this) : null;
@@ -186,11 +177,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
return manyToMany && !excludedFromHistory && descriptor.isHistorySupport();
}
@Override
protected void docStoreIncludeByDefault(PathProperties pathProps) {
// by default not including "Many" properties in document store
}
@Override
public void registerColumn(BeanDescriptor<?> desc, String prefix) {
if (targetDescriptor != null) {
@@ -352,13 +338,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
}
}
public void addWhereParentIdIn(SpiQuery<?> query, List<Object> parentIds, boolean useDocStore) {
if (useDocStore) {
// assumes the ManyToOne property is included
query.where().in(childMasterIdProperty, parentIds);
} else {
sqlHelp.addWhereParentIdIn(query, parentIds);
}
public void addWhereParentIdIn(SpiQuery<?> query, List<Object> parentIds) {
sqlHelp.addWhereParentIdIn(query, parentIds);
}
/**
@@ -375,7 +356,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
}
private IntersectionTable initIntersectionTable() {
IntersectionBuilder row = new IntersectionBuilder(intersectionPublishTable, intersectionDraftTable);
IntersectionBuilder row = new IntersectionBuilder(intersectionJoin.getTable());
for (ExportedProperty exportedProperty : exportedProperties) {
row.addColumn(exportedProperty.getForeignDbColumn());
}
@@ -437,7 +418,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
StringBuilder sb = new StringBuilder(50).append("from "); // use from to stop parsing on table name
SpiQuery<?> query = request.queryRequest().query();
if (hasJoinTable()) {
sb.append(query.isAsDraft() ? intersectionDraftTable : intersectionPublishTable);
sb.append(intersectionJoin.getTable());
} else {
sb.append(targetDescriptor.baseTable(query.temporalMode()));
}
@@ -767,37 +748,21 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
return row;
}
public IntersectionRow buildManyToManyDeleteChildren(EntityBean parentBean, boolean publish) {
String tableName = publish ? intersectionPublishTable : intersectionDraftTable;
public IntersectionRow buildManyToManyDeleteChildren(EntityBean parentBean) {
String tableName = intersectionJoin.getTable();
IntersectionRow row = new IntersectionRow(tableName);
buildExport(row, parentBean);
return row;
}
public IntersectionRow buildManyToManyMapBean(EntityBean parent, EntityBean other, boolean publish) {
String tableName = publish ? intersectionPublishTable : intersectionDraftTable;
public IntersectionRow buildManyToManyMapBean(EntityBean parent, EntityBean other) {
String tableName = intersectionJoin.getTable();
IntersectionRow row = new IntersectionRow(tableName);
buildExport(row, parent);
buildImport(row, other);
return row;
}
/**
* Register the mapping of intersection table to associated draft table.
*/
void registerDraftIntersectionTable(BeanDescriptorInitContext initContext) {
if (hasDraftIntersection()) {
initContext.addDraftIntersection(intersectionPublishTable, intersectionDraftTable);
}
}
/**
* Return true if the relationship is a ManyToMany with the intersection having an associated draft table.
*/
private boolean hasDraftIntersection() {
return intersectionDraftTable != null && !intersectionDraftTable.equals(intersectionPublishTable);
}
/**
* Bind the two side of a many to many to the given SqlUpdate.
*/
@@ -882,55 +847,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
jsonHelp.jsonRead(readJson, parentBean);
}
@SuppressWarnings("unchecked")
void publishMany(EntityBean draft, EntityBean live) {
// collections will not be null due to enhancement
BeanCollection<T> draftVal = (BeanCollection<T>) getValueIntercept(draft);
BeanCollection<T> liveVal = (BeanCollection<T>) getValueIntercept(live);
// Organise the existing live beans into map keyed by id
Map<Object, T> liveBeansAsMap = liveBeansAsMap(liveVal);
// publish from each draft to live bean creating new live beans as required
draftVal.size();
Collection<T> actualDetails = draftVal.actualDetails();
for (T bean : actualDetails) {
Object id = targetDescriptor.id(bean);
T liveBean = liveBeansAsMap.remove(id);
if (isManyToMany()) {
if (liveBean == null) {
// add new relationship (Map not allowed here)
liveVal.addBean(targetDescriptor.createReference(id, null));
}
} else {
// recursively publish the OneToMany child bean
T newLive = targetDescriptor.publish(bean, liveBean);
if (liveBean == null) {
// Map not allowed here
liveVal.addBean(newLive);
}
}
}
// anything remaining should be deleted (so remove from modify aware collection)
Collection<T> values = liveBeansAsMap.values();
for (T value : values) {
liveVal.removeBean(value);
}
}
@SuppressWarnings("unchecked")
private Map<Object, T> liveBeansAsMap(BeanCollection<?> liveVal) {
liveVal.size();
Collection<?> liveBeans = liveVal.actualDetails();
Map<Object, T> liveMap = new LinkedHashMap<>();
for (Object liveBean : liveBeans) {
Object id = targetDescriptor.id(liveBean);
liveMap.put(id, (T) liveBean);
}
return liveMap;
}
public boolean isIncludeCascadeSave() {
// Note ManyToMany always included as we always 'save'
// the relationship via insert/delete of intersection table
@@ -950,10 +866,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
return sqlHelp.insertElementCollection();
}
public boolean isTargetDocStoreMapped() {
return targetDescriptor.isDocStoreMapped();
}
void jsonWriteMapEntry(SpiJsonWriter ctx, Map.Entry<?, ?> entry) throws IOException {
if (elementDescriptor != null) {
elementDescriptor.jsonWriteMapEntry(ctx, entry);
@@ -17,7 +17,6 @@ import io.ebeaninternal.api.json.SpiJsonReader;
import io.ebeaninternal.api.json.SpiJsonWriter;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.cache.CachedBeanData;
import io.ebeaninternal.server.cache.CachedBeanId;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.deploy.id.ImportedId;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
@@ -125,6 +124,9 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
// no imported or exported information
} else if (!oneToOneExported) {
importedId = createImportedId(this, targetDescriptor, tableJoin);
if (importedId == null) {
throw new IllegalStateException("Missing @Id property on " + targetDescriptor);
}
if (importedId.isScalar()) {
// limit JoinColumn mapping to the @Id / primary key
TableJoinColumn[] columns = tableJoin.columns();
@@ -319,15 +321,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
prefix = SplitName.add(prefix, name);
if (!embedded) {
InheritInfo inheritInfo = targetDescriptor.inheritInfo();
if (inheritInfo != null) {
// expect the discriminator column to be included in order
// to determine the inheritance type so we add it to the
// selectChain (so that it takes a position in the resultSet)
String discriminatorColumn = inheritInfo.getDiscriminatorColumn();
String discProperty = prefix + "." + discriminatorColumn;
selectChain.add(discProperty);
}
if (targetIdBinder == null) {
throw new IllegalStateException("No Id binding property for " + fullName()
+ ". Probably a missing @OneToOne mapping annotation on this relationship?");
@@ -420,19 +413,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
}
if (embedded) {
return targetDescriptor.cacheEmbeddedBeanExtract((EntityBean) ap);
} else if (targetInheritInfo != null) {
return createCacheBeanId(ap);
} else {
return targetDescriptor.idProperty().getCacheDataValue((EntityBean) ap);
}
}
private Object createCacheBeanId(Object bean) {
final BeanDescriptor<?> desc = targetDescriptor.descOf(bean.getClass());
final Object id = desc.idProperty().getCacheDataValue((EntityBean) bean);
return new CachedBeanId(desc.discValue(), id);
}
@Override
public String format(Object value) {
return targetDescriptor.idBinder().cacheKey(value);
@@ -446,20 +431,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
if (embedded) {
setValue(bean, targetDescriptor.cacheEmbeddedBeanLoad((CachedBeanData) cacheData, context));
} else {
if (cacheData instanceof CachedBeanId) {
setValue(bean, refInheritBean((CachedBeanId) cacheData, context));
} else {
setValue(bean, refBean(targetDescriptor, cacheData, context));
}
setValue(bean, refBean(targetDescriptor, cacheData, context));
}
}
}
private Object refInheritBean(CachedBeanId cacheId, PersistenceContext context) {
final InheritInfo rowInheritInfo = targetInheritInfo.readType(cacheId.getDiscValue());
return refBean(rowInheritInfo.desc(), cacheId.getId(), context);
}
private Object refBean(BeanDescriptor<?> desc, Object id, PersistenceContext context) {
if (id instanceof String) {
id = desc.idProperty().scalarType.parse((String) id);
@@ -718,11 +694,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
} else if (oneToOneExported) {
return new AssocOneHelpRefExported(this);
} else {
if (targetInheritInfo != null) {
return new AssocOneHelpRefInherit(this);
} else {
return new AssocOneHelpRefSimple(this, embeddedPrefix);
}
return new AssocOneHelpRefSimple(this, embeddedPrefix);
}
}
@@ -79,11 +79,6 @@ public interface DbReadContext {
*/
SpiQuery.Mode queryMode();
/**
* Return true if the underlying query is a 'asDraft' query.
*/
boolean isDraftQuery();
/**
* Return true if this request disables lazy loading.
*/
@@ -124,11 +124,6 @@ public interface DbSqlContext {
*/
int asOfTableCount();
/**
* Return true if the query is a 'asDraft' query.
*/
boolean isDraftQuery();
/**
* Start group by clause.
*/
@@ -1,78 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.annotation.DocCode;
import io.ebean.annotation.DocProperty;
import io.ebean.annotation.DocSortable;
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
/**
* The options for document property collected when reading deployment mapping.
*/
public final class DeployDocPropertyOptions {
private static final DocPropertyOptions EMPTY = new DocPropertyOptions();
private DocPropertyOptions mapping;
private void createOptions() {
if (mapping == null) {
mapping = new DocPropertyOptions();
}
}
/**
* Read the DocProperty deployment options.
*/
public void setDocProperty(DocProperty doc) {
createOptions();
mapping.apply(doc);
}
/**
* Read the DocSortable deployment options.
*/
public void setDocSortable(DocSortable doc) {
createOptions();
mapping.sortable(true);
setStore(doc.store());
setBoost(doc.boost());
setNullValue(doc.nullValue());
}
/**
* Read the DocCode deployment options.
*/
public void setDocCode(DocCode doc) {
createOptions();
mapping.code(true);
setStore(doc.store());
setBoost(doc.boost());
setNullValue(doc.nullValue());
}
private void setNullValue(String value) {
if (!value.isEmpty()) {
mapping.nullValue(value);
}
}
private void setBoost(float boost) {
if (Float.compare(boost, 1.0F) != 0) {
mapping.boost(boost);
}
}
private void setStore(boolean store) {
if (store) {
mapping.store(true);
}
}
/**
* Return the DocPropertyOptions with the collected options.
*/
public DocPropertyOptions create() {
return (mapping == null) ? EMPTY : mapping;
}
}
@@ -1,360 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.server.core.InternString;
import io.ebeaninternal.server.deploy.id.IdBinder;
import io.ebeaninternal.server.deploy.parse.DeployInheritInfo;
import io.ebeaninternal.server.query.SqlTreeProperties;
import jakarta.persistence.PersistenceException;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
/**
* Represents a node in the Inheritance tree. Holds information regarding Super Subclass support.
*/
public final class InheritInfo {
private final String discriminatorStringValue;
private final Object discriminatorValue;
private final String discriminatorColumn;
private final int discriminatorType;
private final int discriminatorLength;
private final String columnDefn;
private final String where;
private final Class<?> type;
private final List<InheritInfo> children = new ArrayList<>();
/**
* Map of discriminator values to InheritInfo.
*/
private final HashMap<String, InheritInfo> discMap;
/**
* Map of class types to InheritInfo (taking into account subclass proxy classes).
*/
private final HashMap<String, InheritInfo> typeMap;
private final InheritInfo parent;
private final InheritInfo root;
private BeanDescriptor<?> descriptor;
public InheritInfo(InheritInfo r, InheritInfo parent, DeployInheritInfo deploy) {
this.parent = parent;
this.type = deploy.getType();
this.discriminatorColumn = InternString.intern(deploy.getColumnName(parent));
this.discriminatorValue = deploy.getDiscriminatorObjectValue();
this.discriminatorStringValue = deploy.getDiscriminatorStringValue();
this.discriminatorType = deploy.getDiscriminatorType(parent);
this.discriminatorLength = deploy.getColumnLength(parent);
this.columnDefn = deploy.getColumnDefn();
this.where = InternString.intern(deploy.getWhere());
if (r == null) {
// this is a root node
root = this;
discMap = new HashMap<>();
typeMap = new HashMap<>();
registerWithRoot(this);
} else {
this.root = r;
// register with the root node...
discMap = null;
typeMap = null;
root.registerWithRoot(this);
}
}
/**
* Visit all the children in the inheritance tree.
*/
public void visitChildren(InheritInfoVisitor visitor) {
for (InheritInfo child : children) {
visitor.visit(child);
child.visitChildren(visitor);
}
}
/**
* Append check constraint values for the entire inheritance hierarchy.
*/
public void appendCheckConstraintValues(final String propertyName, final Set<String> checkConstraintValues) {
visitChildren(inheritInfo -> {
BeanProperty prop = inheritInfo.desc().beanProperty(propertyName);
if (prop != null) {
Set<String> values = prop.dbCheckConstraintValues();
if (values != null) {
checkConstraintValues.addAll(values);
}
}
});
}
/**
* return true if anything in the inheritance hierarchy has a relationship with a save cascade on
* it.
*/
boolean isSaveRecurseSkippable() {
return root.isNodeSaveRecurseSkippable();
}
private boolean isNodeSaveRecurseSkippable() {
if (!descriptor.isSaveRecurseSkippable()) {
return false;
}
for (InheritInfo child : children) {
if (!child.isNodeSaveRecurseSkippable()) {
return false;
}
}
return true;
}
/**
* return true if anything in the inheritance hierarchy has a relationship with a delete cascade
* on it.
*/
boolean isDeleteRecurseSkippable() {
return root.isNodeDeleteRecurseSkippable();
}
private boolean isNodeDeleteRecurseSkippable() {
if (!descriptor.isDeleteRecurseSkippable()) {
return false;
}
for (InheritInfo child : children) {
if (!child.isNodeDeleteRecurseSkippable()) {
return false;
}
}
return true;
}
/**
* Set the descriptor for this node.
*/
public void setDescriptor(BeanDescriptor<?> descriptor) {
this.descriptor = descriptor;
}
/**
* Return the associated BeanDescriptor for this node.
*/
public BeanDescriptor<?> desc() {
return descriptor;
}
/**
* Return the local properties for this node in the hierarchy.
*/
public BeanProperty[] localProperties() {
return descriptor.propertiesLocal();
}
/**
* Return the children.
*/
public List<InheritInfo> getChildren() {
return children;
}
/**
* Return true if this node has children.
* <p>
* When an inheritance node has no children then we don't need
* the discriminator column as the type is effectively known.
*/
public boolean hasChildren() {
return !children.isEmpty();
}
/**
* Get the bean property additionally looking in the sub types.
*/
BeanProperty findSubTypeProperty(String propertyName) {
BeanProperty prop;
for (InheritInfo childInfo : children) {
// recursively search this child bean descriptor
prop = childInfo.desc().findProperty(propertyName);
if (prop != null) {
return prop;
}
}
return null;
}
/**
* Add the local properties for each sub class below this one.
*/
public void addChildrenProperties(SqlTreeProperties selectProps) {
for (InheritInfo childInfo : children) {
selectProps.add(childInfo.descriptor.propertiesLocal());
childInfo.addChildrenProperties(selectProps);
}
}
/**
* Return the associated InheritInfo for this DB row read.
*/
public InheritInfo readType(DbReadContext ctx) throws SQLException {
return readType(ctx.dataReader().getString());
}
/**
* Return the associated InheritInfo for this discriminator value.
*/
InheritInfo readType(String discValue) {
if (discValue == null) {
return null;
}
InheritInfo typeInfo = root.getType(discValue);
if (typeInfo == null) {
throw new PersistenceException("Inheritance type for discriminator value [" + discValue + "] was not found?");
}
return typeInfo;
}
/**
* Return the associated InheritInfo for this bean type.
*/
public InheritInfo readType(Class<?> beanType) {
InheritInfo typeInfo = root.getTypeByClass(beanType);
if (typeInfo == null) {
throw new PersistenceException("Inheritance type for bean type [" + beanType.getName() + "] was not found?");
}
return typeInfo;
}
/**
* Create an EntityBean for this type.
*/
public EntityBean createEntityBean() {
return descriptor.createEntityBean();
}
/**
* Return the IdBinder for this type.
*/
public IdBinder getIdBinder() {
return descriptor.idBinder();
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the root node of the tree.
* <p>
* The root has a map of discriminator values to types.
* </p>
*/
public InheritInfo getRoot() {
return root;
}
/**
* Return the parent node.
*/
public InheritInfo getParent() {
return parent;
}
/**
* Return true if this is the root node.
*/
public boolean isRoot() {
return parent == null;
}
/**
* Return true if this is considered a concrete type in the inheritance hierarchy.
*/
public boolean isConcrete() {
return !Modifier.isAbstract(type.getModifiers());
}
/**
* For a discriminator get the inheritance information for this tree.
*/
public InheritInfo getType(String discValue) {
return discMap.get(discValue);
}
/**
* Return the InheritInfo for the given bean type.
*/
private InheritInfo getTypeByClass(Class<?> beanType) {
return typeMap.get(beanType.getName());
}
private void registerWithRoot(InheritInfo info) {
if (info.getDiscriminatorStringValue() != null) {
String stringDiscValue = info.getDiscriminatorStringValue();
discMap.put(stringDiscValue, info);
}
typeMap.put(info.getType().getName(), info);
}
/**
* Add a child node.
*/
public void addChild(InheritInfo childInfo) {
children.add(childInfo);
}
/**
* Return the derived where for the discriminator.
*/
public String getWhere() {
return where;
}
/**
* Return the column name of the discriminator.
*/
public String getDiscriminatorColumn() {
return discriminatorColumn;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType() {
return discriminatorType;
}
/**
* Return the length of the discriminator column.
*/
public int getColumnLength() {
return discriminatorLength;
}
/**
* Return the explicit column definition.
*/
public String getColumnDefn() {
return columnDefn;
}
/**
* Return the discriminator value for this node.
*/
String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
public Object getDiscriminatorValue() {
return discriminatorValue;
}
@Override
public String toString() {
return "InheritInfo " + type.getName() + " disc:" + discriminatorStringValue;
}
}
@@ -1,13 +0,0 @@
package io.ebeaninternal.server.deploy;
/**
* Used to visit all the InheritInfo in a single inheritance hierarchy.
*/
public interface InheritInfoVisitor {
/**
* visit the InheritInfo for this node.
*/
void visit(InheritInfo inheritInfo);
}
@@ -8,13 +8,11 @@ import java.util.List;
*/
public final class IntersectionBuilder {
private final String publishTable;
private final String draftTable;
private final String table;
private final List<String> columns = new ArrayList<>();
IntersectionBuilder(String publishTable, String draftTable) {
this.publishTable = publishTable;
this.draftTable = draftTable;
IntersectionBuilder(String table) {
this.table = table;
}
public void addColumn(String column) {
@@ -22,18 +20,9 @@ public final class IntersectionBuilder {
}
public IntersectionTable build() {
String insertSql = insertSql(publishTable);
String deleteSql = deleteSql(publishTable);
String draftInsertSql;
String draftDeleteSql;
if (publishTable.equals(draftTable)) {
draftInsertSql = insertSql;
draftDeleteSql = deleteSql;
} else {
draftInsertSql = insertSql(draftTable);
draftDeleteSql = deleteSql(draftTable);
}
return new IntersectionTable(insertSql, deleteSql, draftInsertSql, draftDeleteSql);
String insertSql = insertSql(table);
String deleteSql = deleteSql(table);
return new IntersectionTable(insertSql, deleteSql);
}
private String insertSql(String tableName) {
@@ -7,28 +7,24 @@ public final class IntersectionTable {
private final String insertSql;
private final String deleteSql;
private final String draftInsertSql;
private final String draftDeleteSql;
IntersectionTable(String insertSql, String deleteSql, String draftInsertSql, String draftDeleteSql) {
IntersectionTable(String insertSql, String deleteSql) {
this.insertSql = insertSql;
this.deleteSql = deleteSql;
this.draftInsertSql = draftInsertSql;
this.draftDeleteSql = draftDeleteSql;
}
/**
* Return a SqlUpdate for inserting into the intersection table.
*/
public SqlUpdate insert(Database server, boolean draft) {
return server.sqlUpdate(draft ? draftInsertSql : insertSql);
public SqlUpdate insert(Database server) {
return server.sqlUpdate(insertSql);
}
/**
* Return a SqlUpdate for deleting from the intersection table.
*/
public SqlUpdate delete(Database server, boolean draft) {
return server.sqlUpdate(draft ? draftDeleteSql : deleteSql);
public SqlUpdate delete(Database server) {
return server.sqlUpdate(deleteSql);
}
}
@@ -21,8 +21,6 @@ public final class TableJoin {
*/
private final SqlJoinType type;
private final InheritInfo inheritInfo;
/**
* Columns as an array.
*/
@@ -49,7 +47,6 @@ public final class TableJoin {
this.extraWhere = deploy.getExtraWhere();
this.table = InternString.intern(deploy.getTable());
this.type = deploy.getType();
this.inheritInfo = deploy.getInheritInfo();
DeployTableJoinColumn[] deployCols = deploy.columns();
this.columns = new TableJoinColumn[deployCols.length];
for (int i = 0; i < deployCols.length; i++) {
@@ -63,7 +60,6 @@ public final class TableJoin {
this.extraWhere = source.extraWhere;
this.table = source.table;
this.type = source.type;
this.inheritInfo = source.inheritInfo;
this.columns = new TableJoinColumn[1];
this.columns[0] = source.columns[0].withOverrideColumn(overrideColumn);
this.queryHash = calcQueryHash();
@@ -2,15 +2,12 @@ package io.ebeaninternal.server.deploy.meta;
import io.ebean.DatabaseBuilder;
import io.ebean.annotation.Cache;
import io.ebean.annotation.DocStore;
import io.ebean.annotation.DocStoreMode;
import io.ebean.annotation.Identity;
import io.ebean.config.TableName;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.event.*;
import io.ebean.event.changelog.ChangeLogFilter;
import io.ebean.text.PathProperties;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.ConcurrencyMode;
import io.ebeaninternal.server.core.CacheOptions;
@@ -20,9 +17,6 @@ import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
import io.ebeaninternal.server.idgen.UuidV4IdGenerator;
import io.ebeaninternal.server.rawsql.SpiRawSql;
import jakarta.persistence.Entity;
import jakarta.persistence.MappedSuperclass;
import java.lang.reflect.Field;
import java.util.*;
@@ -32,10 +26,6 @@ import java.util.*;
*/
public class DeployBeanDescriptor<T> {
private static final Map<String, String> EMPTY_NAMED_QUERY = new HashMap<>();
private static final Map<String, SpiRawSql> EMPTY_RAW_MAP = new HashMap<>();
private static class PropOrder implements Comparator<DeployBeanProperty> {
@Override
@@ -52,8 +42,6 @@ public class DeployBeanDescriptor<T> {
* Map of BeanProperty Linked so as to preserve order.
*/
private LinkedHashMap<String, DeployBeanProperty> propMap = new LinkedHashMap<>();
private Map<String, SpiRawSql> namedRawSql;
private Map<String, String> namedQuery;
private EntityType entityType;
private DeployBeanPropertyAssocOne<?> unidirectional;
private DeployBeanProperty orderColumn;
@@ -69,7 +57,6 @@ public class DeployBeanDescriptor<T> {
* Used with Identity columns but no getGeneratedKeys support.
*/
private String selectLastInsertedId;
private String selectLastInsertedIdDraft;
/**
* The concurrency mode for beans of this type.
*/
@@ -82,12 +69,8 @@ public class DeployBeanDescriptor<T> {
private String baseTable;
private String baseTableAsOf;
private String baseTableVersionsBetween;
private String draftTable;
private String[] dependentTables;
private boolean historySupport;
private boolean readAuditing;
private boolean draftable;
private boolean draftableElement;
private TableName baseTableFull;
private String[] properties;
/**
@@ -107,25 +90,11 @@ public class DeployBeanDescriptor<T> {
/**
* Inheritance information. Server side only.
*/
private InheritInfo inheritInfo;
private String name;
private ChangeLogFilter changeLogFilter;
private String dbComment;
private PartitionMeta partitionMeta;
private TablespaceMeta tablespaceMeta;
/**
* One of NONE, INDEX or EMBEDDED.
*/
private boolean docStoreMapped;
private DocStore docStore;
private PathProperties docStorePathProperties;
private String docStoreQueueId;
private String docStoreIndexName;
private String docStoreIndexType;
private DocStoreMode docStorePersist;
private DocStoreMode docStoreInsert;
private DocStoreMode docStoreUpdate;
private DocStoreMode docStoreDelete;
private DeployBeanProperty idProperty;
private TableJoin primaryKeyJoin;
@@ -218,20 +187,6 @@ public class DeployBeanDescriptor<T> {
return historySupport;
}
/**
* Set read auditing on for this entity bean.
*/
public void setReadAuditing() {
readAuditing = true;
}
/**
* Return true if read auditing is on for this entity bean.
*/
public boolean isReadAuditing() {
return readAuditing;
}
public void setDbComment(String dbComment) {
this.dbComment = dbComment;
}
@@ -262,42 +217,6 @@ public class DeployBeanDescriptor<T> {
return tablespaceMeta;
}
public void setDraftable() {
draftable = true;
}
public boolean isDraftable() {
return draftable;
}
public void setDraftableElement() {
draftable = true;
draftableElement = true;
}
public boolean isDraftableElement() {
return draftableElement;
}
/**
* Read the top level doc store deployment information.
*/
public void readDocStore(DocStore docStore) {
this.docStore = docStore;
docStoreMapped = true;
docStoreQueueId = docStore.queueId();
docStoreIndexName = docStore.indexName();
docStoreIndexType = docStore.indexType();
docStorePersist = docStore.persist();
docStoreInsert = docStore.insert();
docStoreUpdate = docStore.update();
docStoreDelete = docStore.delete();
String doc = docStore.doc();
if (!doc.isEmpty()) {
docStorePathProperties = PathProperties.parse(doc);
}
}
public DeployBeanTable createDeployBeanTable() {
DeployBeanTable beanTable = new DeployBeanTable(getBeanType());
beanTable.setBaseTable(baseTable);
@@ -384,21 +303,6 @@ public class DeployBeanDescriptor<T> {
return changeLogFilter;
}
/**
* Returns the Inheritance mapping information. This will be null if this type
* of bean is not involved in any ORM inheritance mapping.
*/
public InheritInfo getInheritInfo() {
return inheritInfo;
}
/**
* Set the ORM inheritance mapping information.
*/
public void setInheritInfo(InheritInfo inheritInfo) {
this.inheritInfo = inheritInfo;
}
/**
* Set that this type invalidates query caches.
*/
@@ -583,10 +487,6 @@ public class DeployBeanDescriptor<T> {
postConstructListeners.add(postConstructListener);
}
public String getDraftTable() {
return draftTable;
}
/**
* For view based entity return the dependant tables.
*/
@@ -640,7 +540,6 @@ public class DeployBeanDescriptor<T> {
this.baseTable = baseTableFull == null ? null : baseTableFull.getQualifiedName();
this.baseTableAsOf = baseTable + asOfSuffix;
this.baseTableVersionsBetween = baseTable + versionsBetweenSuffix;
this.draftTable = (draftable) ? baseTable + "_draft" : baseTable;
}
public void sortProperties() {
@@ -714,16 +613,11 @@ public class DeployBeanDescriptor<T> {
return selectLastInsertedId;
}
public String getSelectLastInsertedIdDraft() {
return selectLastInsertedIdDraft;
}
/**
* Set the SQL used to return the last inserted Id.
*/
public void setSelectLastInsertedId(String selectLastInsertedId, String selectLastInsertedIdDraft) {
public void setSelectLastInsertedId(String selectLastInsertedId) {
this.selectLastInsertedId = selectLastInsertedId;
this.selectLastInsertedIdDraft = selectLastInsertedIdDraft;
}
/**
@@ -940,126 +834,6 @@ public class DeployBeanDescriptor<T> {
return list;
}
/**
* Check the mapping for class inheritance
*/
public void checkInheritanceMapping() {
if (inheritInfo == null) {
checkInheritance(getBeanType());
}
}
/**
* Check valid mapping annotations on the class hierarchy.
*/
private void checkInheritance(Class<?> beanType) {
Class<?> parent = beanType.getSuperclass();
if (parent == null || Object.class.equals(parent)) {
// all good
return;
}
if (parent.isAnnotationPresent(Entity.class)) {
String msg = "Checking " + getBeanType() + " and found " + parent + " that has @Entity annotation rather than MappedSuperclass?";
throw new IllegalStateException(msg);
}
if (parent.isAnnotationPresent(MappedSuperclass.class)) {
// continue checking
checkInheritance(parent);
}
}
public PathProperties getDocStorePathProperties() {
return docStorePathProperties;
}
/**
* Return true if this type is mapped for a doc store.
*/
public boolean isDocStoreMapped() {
return docStoreMapped;
}
public String getDocStoreQueueId() {
return docStoreQueueId;
}
public String getDocStoreIndexName() {
return docStoreIndexName;
}
public String getDocStoreIndexType() {
return docStoreIndexType;
}
public DocStore getDocStore() {
return docStore;
}
/**
* Return the DocStore index behavior for bean inserts.
*/
public DocStoreMode getDocStoreInsertEvent() {
return getDocStoreIndexEvent(docStoreInsert);
}
/**
* Return the DocStore index behavior for bean updates.
*/
public DocStoreMode getDocStoreUpdateEvent() {
return getDocStoreIndexEvent(docStoreUpdate);
}
/**
* Return the DocStore index behavior for bean deletes.
*/
public DocStoreMode getDocStoreDeleteEvent() {
return getDocStoreIndexEvent(docStoreDelete);
}
private DocStoreMode getDocStoreIndexEvent(DocStoreMode mostSpecific) {
if (!docStoreMapped) {
return DocStoreMode.IGNORE;
}
if (mostSpecific != DocStoreMode.DEFAULT) return mostSpecific;
if (docStorePersist != DocStoreMode.DEFAULT) return docStorePersist;
return config.getDocStoreConfig().getPersist();
}
/**
* Return the named ORM queries.
*/
public Map<String, String> getNamedQuery() {
return (namedQuery != null) ? namedQuery : EMPTY_NAMED_QUERY;
}
/**
* Add a named query.
*/
public void addNamedQuery(String name, String query) {
if (namedQuery == null) {
namedQuery = new LinkedHashMap<>();
}
namedQuery.put(name, query);
}
/**
* Return the named RawSql queries.
*/
public Map<String, SpiRawSql> getNamedRawSql() {
return (namedRawSql != null) ? namedRawSql : EMPTY_RAW_MAP;
}
/**
* Add a named RawSql from ebean.xml file.
*/
public void addRawSql(String name, SpiRawSql rawSql) {
if (namedRawSql == null) {
namedRawSql = new HashMap<>();
}
namedRawSql.put(name, rawSql);
}
/**
* Parse the aggregation formula into expressions with table alias placeholders.
*/
@@ -13,13 +13,11 @@ import io.ebeaninternal.server.core.InternString;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BindMaxLength;
import io.ebeaninternal.server.deploy.DbMigrationInfo;
import io.ebeaninternal.server.deploy.DeployDocPropertyOptions;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.properties.BeanPropertyGetter;
import io.ebeaninternal.server.properties.BeanPropertySetter;
import io.ebeaninternal.server.type.ScalarTypeWrapper;
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.FetchType;
@@ -148,7 +146,6 @@ public class DeployBeanProperty {
* The jdbc data type this maps to.
*/
private int dbType;
private final DeployDocPropertyOptions docMapping = new DeployDocPropertyOptions();
private int propertyIndex;
private BeanPropertyGetter getter;
private BeanPropertySetter setter;
@@ -162,10 +159,6 @@ public class DeployBeanProperty {
private int sortOrder;
private boolean excludedFromHistory;
private boolean tenantId;
private boolean draft;
private boolean draftOnly;
private boolean draftDirty;
private boolean draftReset;
private boolean softDelete;
private boolean unmappedJson;
private String dbComment;
@@ -904,41 +897,6 @@ public class DeployBeanProperty {
this.excludedFromHistory = true;
}
public void setDraft() {
this.draft = true;
this.isTransient = true;
}
public boolean isDraft() {
return draft;
}
public void setDraftOnly() {
this.draftOnly = true;
}
public boolean isDraftOnly() {
return draftOnly;
}
public void setDraftDirty() {
this.draftOnly = true;
this.draftDirty = true;
this.nullable = false;
}
public boolean isDraftDirty() {
return draftDirty;
}
public void setDraftReset() {
this.draftReset = true;
}
public boolean isDraftReset() {
return draftReset;
}
/**
* Primitive boolean check so see if not null default false should be applied.
*/
@@ -981,22 +939,6 @@ public class DeployBeanProperty {
return dbComment;
}
public void setDocProperty(DocProperty docProperty) {
docMapping.setDocProperty(docProperty);
}
public void setDocSortable(DocSortable docSortable) {
docMapping.setDocSortable(docSortable);
}
public void setDocCode(DocCode docCode) {
docMapping.setDocCode(docCode);
}
public DocPropertyOptions getDocPropertyOptions() {
return docMapping.create();
}
/**
* Return the DB Column default taking into account literal translation.
*/
@@ -33,7 +33,6 @@ public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
* From the deployment mappedBy attribute.
*/
private String mappedBy;
private String docStoreDoc;
private int fetchPreference = 1000;
private PropertyForeignKey foreignKey;
boolean orphanRemoval;
@@ -150,17 +149,6 @@ public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
return orphanRemoval;
}
/**
* Set DocStoreEmbedded deployment information.
*/
public void setDocStoreEmbedded(String embeddedDoc) {
this.docStoreDoc = embeddedDoc;
}
public String getDocStoreDoc() {
return docStoreDoc;
}
public int getFetchPreference() {
return fetchPreference;
}
@@ -38,7 +38,6 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
private DeployTableJoin inverseJoin;
private String fetchOrderBy;
private String mapKey;
private String intersectionDraftTable;
private DeployOrderColumn orderColumn;
/**
* Effectively the dynamically created target descriptor (that doesn't have a mapped type/class per say).
@@ -191,20 +190,6 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
}
}
/**
* Return a draft table for intersection between 2 @Draftable entities.
*/
public String getIntersectionDraftTable() {
return (intersectionDraftTable != null) ? intersectionDraftTable : intersectionJoin.getTable();
}
/**
* ManyToMany between 2 @Draftable entities to also need draft intersection table.
*/
public void setIntersectionDraftTable() {
this.intersectionDraftTable = intersectionJoin.getTable() + "_draft";
}
public void setOrderColumn(DeployOrderColumn orderColumn) {
this.orderColumn = orderColumn;
}
@@ -5,7 +5,6 @@ import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.deploy.*;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.properties.BeanPropertySetter;
import io.ebeaninternal.server.type.ScalarTypeString;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -22,14 +21,11 @@ public final class DeployBeanPropertyLists {
private BeanProperty versionProperty;
private BeanProperty unmappedJson;
private BeanProperty draft;
private BeanProperty draftDirty;
private BeanProperty tenant;
private final BeanDescriptor<?> desc;
private final LinkedHashMap<String, BeanProperty> propertyMap;
private BeanProperty id;
private final List<BeanProperty> local = new ArrayList<>();
private final List<BeanProperty> mutable = new ArrayList<>();
private final List<BeanPropertyAssocMany<?>> manys = new ArrayList<>();
private final List<BeanProperty> nonManys = new ArrayList<>();
@@ -59,35 +55,9 @@ public final class DeployBeanPropertyLists {
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
this.unidirectional = deployUnidirectional == null ? null : new BeanPropertyAssocOne<>(owner, desc, deployUnidirectional);
this.propertyMap = new LinkedHashMap<>();
// see if there is a discriminator property we should add
String discriminatorColumn = null;
BeanProperty discProperty = null;
InheritInfo inheritInfo = deploy.getInheritInfo();
if (inheritInfo != null) {
// Create a BeanProperty for the discriminator column to support
// using RawSql queries with inheritance
discriminatorColumn = inheritInfo.getDiscriminatorColumn();
DeployBeanProperty discDeployProp = new DeployBeanProperty(deploy, String.class, ScalarTypeString.INSTANCE, null);
discDeployProp.setDiscriminator();
discDeployProp.setName(discriminatorColumn);
discDeployProp.setDbColumn(discriminatorColumn);
discDeployProp.setSetter(NOOP_SETTER);
// only register it in the propertyMap. This might not be used if
// an explicit property is mapped to the discriminator on the bean
discProperty = new BeanProperty(desc, discDeployProp);
}
for (DeployBeanProperty prop : deploy.propertiesAll()) {
if (discriminatorColumn != null && discriminatorColumn.equals(prop.getDbColumn())) {
// we have an explicit property mapped to the discriminator column
prop.setDiscriminator();
discProperty = null;
}
BeanProperty beanProp = createBeanProperty(owner, prop);
propertyMap.put(beanProp.name(), beanProp);
}
@@ -103,12 +73,6 @@ public final class DeployBeanPropertyLists {
allocateToList(orderColumn);
propertyMap.put(orderColumn.name(), orderColumn);
}
if (discProperty != null) {
// put the discriminator property into the property map only
// (after the real properties have been organised into their lists)
propertyMap.put(discProperty.name(), discProperty);
}
}
/**
@@ -173,9 +137,6 @@ public final class DeployBeanPropertyLists {
private void allocateToList(BeanProperty prop) {
if (prop.isTransient()) {
transients.add(prop);
if (prop.isDraft()) {
draft = prop;
}
if (prop.isUnmappedJson()) {
unmappedJson = prop;
}
@@ -193,10 +154,6 @@ public final class DeployBeanPropertyLists {
mutable.add(prop);
}
if (desc.inheritInfo() != null && prop.isLocal()) {
local.add(prop);
}
if (prop instanceof BeanPropertyAssocMany<?>) {
manys.add((BeanPropertyAssocMany<?>) prop);
@@ -226,8 +183,6 @@ public final class DeployBeanPropertyLists {
} else {
CoreLog.internal.log(WARNING, "Multiple @Version properties - property " + prop.fullName() + " not treated as a version property");
}
} else if (prop.isDraftDirty()) {
draftDirty = prop;
}
if (!prop.isAggregation()) {
baseScalar.add(prop);
@@ -264,10 +219,6 @@ public final class DeployBeanPropertyLists {
return versionProperty;
}
public BeanProperty[] getLocal() {
return local.toArray(new BeanProperty[0]);
}
public BeanProperty[] getMutable() {
return mutable.toArray(new BeanProperty[0]);
}
@@ -324,18 +275,10 @@ public final class DeployBeanPropertyLists {
return getMany2Many();
}
public BeanProperty getDraftDirty() {
return draftDirty;
}
public BeanProperty getUnmappedJson() {
return unmappedJson;
}
public BeanProperty getDraft() {
return draft;
}
public BeanProperty getSoftDeleteProperty() {
for (BeanProperty prop : nonManys) {
if (prop.isSoftDelete()) {
@@ -1,7 +1,6 @@
package io.ebeaninternal.server.deploy.meta;
import io.ebeaninternal.server.deploy.BeanTable;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.parse.DeployUtil;
import io.ebeaninternal.server.query.SqlJoinType;
@@ -29,7 +28,6 @@ public final class DeployTableJoin {
* The list of join column pairs. Used to generate the on clause.
*/
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<>(4);
private InheritInfo inheritInfo;
private String extraWhere;
/**
@@ -171,14 +169,6 @@ public final class DeployTableJoin {
return destJoin;
}
public InheritInfo getInheritInfo() {
return inheritInfo;
}
public void setInheritInfo(InheritInfo inheritInfo) {
this.inheritInfo = inheritInfo;
}
/**
* Change the join column (based on imported primary key match on property name etc).
*/
@@ -227,9 +227,6 @@ final class AnnotationAssocOnes extends AnnotationAssoc {
}
private void readEmbedded(DeployBeanPropertyAssocOne<?> prop, Embedded embedded) {
if (descriptor.isDocStoreOnly() && prop.getDocStoreDoc() == null) {
prop.setDocStoreEmbedded("");
}
prop.setEmbedded();
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
@@ -6,7 +6,6 @@ import io.ebean.config.TableName;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import io.ebeaninternal.server.deploy.IndexDefinition;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.PartitionMeta;
import io.ebeaninternal.server.deploy.TablespaceMeta;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
@@ -69,10 +68,6 @@ final class AnnotationClass extends AnnotationParser {
private void setTableName() {
if (descriptor.isBaseTableType()) {
Class<?> beanType = descriptor.getBeanType();
InheritInfo inheritInfo = descriptor.getInheritInfo();
if (inheritInfo != null) {
beanType = inheritInfo.getRoot().getType();
}
// default the TableName using NamingConvention.
TableName tableName = namingConvention.getTableName(beanType);
descriptor.setBaseTable(tableName, asOfViewSuffix, versionsBetweenSuffix);
@@ -83,7 +78,6 @@ final class AnnotationClass extends AnnotationParser {
// maybe doc store only so check for this before @Entity
DocStore docStore = typeGet(cls, DocStore.class);
if (docStore != null) {
descriptor.readDocStore(docStore);
descriptor.setEntityType(EntityType.DOC);
descriptor.setName(cls.getSimpleName());
}
@@ -156,15 +150,15 @@ final class AnnotationClass extends AnnotationParser {
}
Draftable draftable = typeGet(cls, Draftable.class);
if (draftable != null) {
descriptor.setDraftable();
//TODO: Not Supported
}
DraftableElement draftableElement = typeGet(cls, DraftableElement.class);
if (draftableElement != null) {
descriptor.setDraftableElement();
//TODO: Not Supported
}
ReadAudit readAudit = typeGet(cls, ReadAudit.class);
if (readAudit != null) {
descriptor.setReadAuditing();
// TODO: Not supported
}
History history = typeGet(cls, History.class);
if (history != null) {
@@ -186,7 +180,7 @@ final class AnnotationClass extends AnnotationParser {
}
}
for (NamedQuery namedQuery : annotationClassNamedQuery(cls)) {
descriptor.addNamedQuery(namedQuery.name(), namedQuery.query());
// TODO: throw new UnsupportedOperationException("NamedQuery not supported");
}
}
@@ -78,17 +78,8 @@ final class AnnotationFields extends AnnotationParser {
prop.setEmbedded();
info.setEmbeddedId(prop);
}
DocEmbedded docEmbedded = get(prop, DocEmbedded.class);
if (docEmbedded != null) {
prop.setDocStoreEmbedded(docEmbedded.doc());
if (descriptor.isDocStoreOnly()) {
if (has(prop, ManyToOne.class)) {
prop.setEmbedded();
prop.setDbInsertable(true);
prop.setDbUpdateable(true);
}
}
}
// TODO: Not Supported - DocEmbedded docEmbedded = get(prop, DocEmbedded.class);
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
if (prop.isId() && !prop.isEmbedded()) {
prop.setEmbedded();
@@ -209,16 +200,7 @@ final class AnnotationFields extends AnnotationParser {
prop.setTenantId();
}
if (has(prop, Draft.class)) {
prop.setDraft();
}
if (has(prop, DraftOnly.class)) {
prop.setDraftOnly();
}
if (has(prop, DraftDirty.class)) {
prop.setDraftDirty();
}
if (has(prop, DraftReset.class)) {
prop.setDraftReset();
// TODO: Not Supported
}
if (has(prop, SoftDelete.class)) {
prop.setSoftDelete();
@@ -254,18 +236,10 @@ final class AnnotationFields extends AnnotationParser {
}
private void initFormula(DeployBeanProperty prop) {
DocCode docCode = get(prop, DocCode.class);
if (docCode != null) {
prop.setDocCode(docCode);
}
DocSortable docSortable = get(prop, DocSortable.class);
if (docSortable != null) {
prop.setDocSortable(docSortable);
}
DocProperty docProperty = get(prop, DocProperty.class);
if (docProperty != null) {
prop.setDocProperty(docProperty);
}
// TODO: Not Supported - DocCode docCode = get(prop, DocCode.class);
//DocSortable docSortable = get(prop, DocSortable.class);
//DocProperty docProperty = get(prop, DocProperty.class);
Formula formula = prop.getMetaAnnotationFormula(platform);
if (formula != null) {
prop.setSqlFormula(processFormula(formula.select()), processFormula(formula.join()));
@@ -1,10 +1,8 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.RawSql;
import io.ebeaninternal.server.deploy.TableJoin;
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import io.ebeaninternal.server.rawsql.SpiRawSql;
/**
* Wraps information about a bean during deployment parsing.
@@ -42,20 +40,6 @@ public final class DeployBeanInfo<T> {
return util;
}
/**
* Add named RawSql from ebean.xml.
*/
public void addRawSql(String name, RawSql rawSql) {
descriptor.addRawSql(name, (SpiRawSql)rawSql);
}
/**
* Add the named query.
*/
public void addNamedQuery(String name, String query) {
descriptor.addNamedQuery(name, query);
}
/**
* Set that the PK is also a foreign key.
*/
@@ -1,140 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.server.core.bootup.BootupClasses;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Inheritance;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Builds the InheritInfo deployment information.
*/
public final class DeployInherit {
private final Map<Class<?>, DeployInheritInfo> deployMap = new LinkedHashMap<>();
private final Map<Class<?>, InheritInfo> finalMap = new LinkedHashMap<>();
private final BootupClasses bootupClasses;
/**
* Create the InheritInfoDeploy.
*/
public DeployInherit(BootupClasses bootupClasses) {
this.bootupClasses = bootupClasses;
initialise();
}
public void process(DeployBeanDescriptor<?> desc) {
InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
desc.setInheritInfo(inheritInfo);
}
private void initialise() {
findInheritClasses(bootupClasses.getEntities());
buildDeployTree();
buildFinalTree();
}
private void findInheritClasses(List<Class<?>> entityList) {
// go through each class and initialise the info object...
for (Class<?> cls : entityList) {
if (isInheritanceClass(cls)) {
deployMap.put(cls, createInfo(cls));
}
}
}
private void buildDeployTree() {
for (DeployInheritInfo info : deployMap.values()) {
if (!info.isRoot()) {
DeployInheritInfo parent = getInfo(info.getParent());
parent.addChild(info);
}
}
}
private void buildFinalTree() {
for (DeployInheritInfo deploy : deployMap.values()) {
if (deploy.isRoot()) {
// build tree top down...
createFinalInfo(null, null, deploy);
}
}
}
private void createFinalInfo(InheritInfo root, InheritInfo parent, DeployInheritInfo deploy) {
InheritInfo node = new InheritInfo(root, parent, deploy);
if (parent != null) {
parent.addChild(node);
}
finalMap.put(node.getType(), node);
if (root == null) {
root = node;
}
// buildFinalChildren(root, child, deploy);
for (DeployInheritInfo childDeploy : deploy.children()) {
createFinalInfo(root, node, childDeploy);
}
}
/**
* Build the InheritInfo for a given class.
*/
private DeployInheritInfo getInfo(Class<?> cls) {
return deployMap.get(cls);
}
private DeployInheritInfo createInfo(Class<?> cls) {
DeployInheritInfo info = new DeployInheritInfo(cls);
Class<?> parent = findParent(cls);
if (parent != null) {
info.setParent(parent);
}
Inheritance ia = AnnotationUtil.typeGet(cls, Inheritance.class);
if (ia != null) {
ia.strategy();
}
DiscriminatorColumn da = AnnotationUtil.typeGet(cls, DiscriminatorColumn.class);
if (da != null) {
// lowercase the discriminator column for RawSql and JSON
info.setColumnName(da.name().toLowerCase());
DiscriminatorType discriminatorType = da.discriminatorType();
info.setColumnType(discriminatorType);
if (discriminatorType == DiscriminatorType.STRING) {
info.setColumnLength(da.length());
}
info.setColumnDefn(da.columnDefinition());
}
if (!info.isAbstract()) {
DiscriminatorValue dv = AnnotationUtil.get(cls, DiscriminatorValue.class); // do not search recursive
if (dv != null) {
info.setDiscriminatorValue(dv.value());
} else {
info.setDiscriminatorDefaultValue(cls);
}
}
return info;
}
private Class<?> findParent(Class<?> cls) {
Class<?> superCls = cls.getSuperclass();
if (isInheritanceClass(superCls)) {
return superCls;
} else {
return null;
}
}
private boolean isInheritanceClass(Class<?> cls) {
return AnnotationUtil.typeHas(cls, Inheritance.class);
}
}
@@ -1,270 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebeaninternal.server.deploy.InheritInfo;
import java.lang.reflect.Modifier;
import jakarta.persistence.DiscriminatorType;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Represents a node in the Inheritance tree.
* Holds information regarding Super Subclass support.
*/
public final class DeployInheritInfo implements Comparable<DeployInheritInfo> {
/**
* the default discriminator column according to the JPA 1.0 spec.
*/
private static final String DEFAULT_COLUMN_NAME = "dtype";
private String discriminatorStringValue;
private Object discriminatorObjectValue;
private int columnType;
private String columnName;
private int columnLength;
private String columnDefn;
private final Class<?> type;
private Class<?> parent;
private final Set<DeployInheritInfo> children = new TreeSet<>();
/**
* Create for a given type.
*/
DeployInheritInfo(Class<?> type) {
this.type = type;
}
/**
* return the type.
*/
public Class<?> getType() {
return type;
}
/**
* Return the type of the root object.
*/
public Class<?> getParent() {
return parent;
}
/**
* Set the type of the root object.
*/
public void setParent(Class<?> parent) {
this.parent = parent;
}
/**
* Return true if this is abstract node.
*/
public boolean isAbstract() {
return Modifier.isAbstract(type.getModifiers());
}
/**
* Return true if this is the root node.
*/
public boolean isRoot() {
return parent == null;
}
/**
* Return the child nodes.
*/
public Set<DeployInheritInfo> children() {
return children;
}
/**
* Add a child node.
*/
public void addChild(DeployInheritInfo childInfo) {
children.add(childInfo);
}
/**
* Return the column name of the discriminator.
*/
public String getColumnName(InheritInfo parent) {
if (columnName == null) {
if (parent == null) {
columnName = DEFAULT_COLUMN_NAME;
} else {
columnName = parent.getDiscriminatorColumn();
}
}
return columnName;
}
/**
* Set the column name of the discriminator.
*/
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public int getColumnLength(InheritInfo parent) {
if (columnLength == 0) {
if (parent == null) {
columnLength = 31;
} else {
columnLength = parent.getColumnLength();
}
}
return columnLength;
}
/**
* Return the sql type of the discriminator value.
*/
public int getDiscriminatorType(InheritInfo parent) {
if (columnType == 0) {
if (parent == null) {
columnType = Types.VARCHAR;
} else {
columnType = parent.getDiscriminatorType();
}
}
return columnType;
}
/**
* Set the sql type of the discriminator.
*/
void setColumnType(DiscriminatorType type) {
if (type == DiscriminatorType.INTEGER) {
this.columnType = Types.INTEGER;
} else {
this.columnType = Types.VARCHAR;
}
}
/**
* Set explicit column definition (ddl).
*/
void setColumnDefn(String columnDefn) {
this.columnDefn = columnDefn;
}
/**
* Return the explicit column definition.
*/
public String getColumnDefn() {
return columnDefn;
}
/**
* Set the length of the discriminator column.
*/
void setColumnLength(int columnLength) {
this.columnLength = columnLength;
}
/**
* Return the discriminator value for this node.
*/
public Object getDiscriminatorObjectValue() {
return discriminatorObjectValue;
}
public String getDiscriminatorStringValue() {
return discriminatorStringValue;
}
public void setDiscriminatorDefaultValue(Class<?> cls) {
if (columnType == Types.INTEGER) {
discriminatorStringValue = "0";
discriminatorObjectValue = 0;
} else {
discriminatorStringValue = cls.getSimpleName();
discriminatorObjectValue = discriminatorStringValue;
}
}
/**
* Set the discriminator value for this node.
*/
void setDiscriminatorValue(String value) {
if (value != null) {
value = value.trim();
if (!value.isEmpty()) {
discriminatorStringValue = value;
// convert the value if desired
if (columnType == Types.INTEGER) {
this.discriminatorObjectValue = Integer.valueOf(value);
} else {
this.discriminatorObjectValue = value;
}
}
}
}
public String getWhere() {
List<Object> discList = new ArrayList<>();
appendDiscriminator(discList);
return buildWhereLiteral(discList);
}
private void appendDiscriminator(List<Object> list) {
if (!isAbstract()) {
list.add(discriminatorObjectValue);
}
for (DeployInheritInfo child : children) {
child.appendDiscriminator(list);
}
}
private String buildWhereLiteral(List<Object> discList) {
int size = discList.size();
if (size == 0) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(columnName);
if (size == 1) {
sb.append(" = ");
} else {
sb.append(" in (");
}
for (int i = 0; i < discList.size(); i++) {
appendSqlLiteralValue(i, discList.get(i), sb);
}
if (size > 1) {
sb.append(')');
}
return sb.toString();
}
private void appendSqlLiteralValue(int count, Object value, StringBuilder sb) {
if (count > 0) {
sb.append(',');
}
if (value instanceof String) {
sb.append('\'').append(value).append('\'');
} else {
sb.append(value);
}
}
@Override
public String toString() {
String root = parent == null ? null : parent.getName();
String name = type == null ? null : type.getName();
return "InheritInfo " + name + " root:" + root + " disc:" + discriminatorStringValue;
}
@Override
public int compareTo(DeployInheritInfo other) {
if (other == this) {
return 0;
} else {
return type.getName().compareTo(other.type.getName());
}
}
}
@@ -4,8 +4,6 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.InheritInfoVisitor;
/**
* Makes use of BeanVisitor and PropertyVisitor to navigate BeanDescriptors
@@ -34,7 +32,6 @@ public class VisitProperties {
visit(propertyVisitor, p);
}
}
visitInheritanceProperties(desc, propertyVisitor);
propertyVisitor.visitEnd();
}
@@ -68,40 +65,4 @@ public class VisitProperties {
}
}
/**
* Visit all the other inheritance properties that are not on the root.
*/
protected void visitInheritanceProperties(BeanDescriptor<?> descriptor, BeanPropertyVisitor pv) {
InheritInfo inheritInfo = descriptor.inheritInfo();
if (inheritInfo != null && inheritInfo.isRoot()) {
// add all properties on the children objects
inheritInfo.visitChildren(new InheritChildVisitor(this, pv));
}
}
/**
* Helper used to visit all the inheritInfo/BeanDescriptor in
* the inheritance hierarchy (to add their 'local' properties).
*/
protected static class InheritChildVisitor implements InheritInfoVisitor {
private final VisitProperties owner;
private final BeanPropertyVisitor pv;
protected InheritChildVisitor(VisitProperties owner, BeanPropertyVisitor pv) {
this.owner = owner;
this.pv = pv;
}
@Override
public void visit(InheritInfo inheritInfo) {
for (BeanProperty beanProperty : inheritInfo.desc().propertiesLocal()) {
if (beanProperty.isDDLColumn()) {
owner.visit(pv, beanProperty);
}
}
}
}
}
@@ -13,12 +13,10 @@ public final class DtoBeanDescriptor<T> {
private final Map<Object, DtoQueryPlan> plans = new ConcurrentHashMap<>();
private final Class<T> dtoType;
private final DtoMeta meta;
private final Map<String, String> namedQueries;
DtoBeanDescriptor(Class<T> dtoType, DtoMeta meta, Map<String, String> namedQueries) {
DtoBeanDescriptor(Class<T> dtoType, DtoMeta meta) {
this.dtoType = dtoType;
this.meta = meta;
this.namedQueries = namedQueries;
}
public Class<T> type() {
@@ -43,11 +41,4 @@ public final class DtoBeanDescriptor<T> {
}
}
/**
* Return the named RawSql query.
*/
public String namedRawSql(String name) {
return namedQueries.get(name);
}
}
@@ -16,12 +16,10 @@ public final class DtoBeanManager {
private static final Map<String,String> EMPTY_NAMED_QUERIES = new HashMap<>();
private final TypeManager typeManager;
private final Map<Class<?>, DtoNamedQueries> namedQueries;
private final Map<Class, DtoBeanDescriptor> descriptorMap = new ConcurrentHashMap<>();
public DtoBeanManager(TypeManager typeManager, Map<Class<?>, DtoNamedQueries> namedQueries) {
public DtoBeanManager(TypeManager typeManager) {
this.typeManager = typeManager;
this.namedQueries = namedQueries;
}
/**
@@ -35,17 +33,12 @@ public final class DtoBeanManager {
private <T> DtoBeanDescriptor createDescriptor(Class<T> dtoType) {
try {
DtoMeta meta = new DtoMetaBuilder(dtoType, typeManager).build();
return new DtoBeanDescriptor<>(dtoType, meta, namedQueries(dtoType));
return new DtoBeanDescriptor<>(dtoType, meta);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
private <T> Map<String, String> namedQueries(Class<T> dtoType) {
DtoNamedQueries namedQueries = this.namedQueries.get(dtoType);
return (namedQueries == null) ? EMPTY_NAMED_QUERIES : namedQueries.map();
}
public void visitMetrics(MetricVisitor visitor) {
for (DtoBeanDescriptor value : descriptorMap.values()) {
value.visit(visitor);
@@ -1,23 +0,0 @@
package io.ebeaninternal.server.dto;
import java.util.HashMap;
import java.util.Map;
/**
* Collection of named queries for a single Dto bean type.
*/
public final class DtoNamedQueries {
private final Map<String, String> namedRawSql = new HashMap<>();
/**
* Add the named query from deployment XML.
*/
public void addRawSql(String name, String query) {
namedRawSql.put(name, query);
}
Map<String, String> map() {
return namedRawSql;
}
}
@@ -1,7 +1,6 @@
package io.ebeaninternal.server.expression;
import io.ebean.event.BeanQueryRequest;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.el.ElPropertyDeploy;
@@ -45,21 +44,6 @@ abstract class AbstractExpression implements SpiExpression {
return this;
}
@Override
public String nestedPath(BeanDescriptor<?> desc) {
return propertyNestedPath(propName, desc);
}
protected String propertyNestedPath(String propertyName, BeanDescriptor<?> desc) {
if (propertyName != null) {
ElPropertyDeploy elProp = desc.elPropertyDeploy(propertyName);
if (elProp != null && elProp.containsMany()) {
return SplitName.begin(propName);
}
}
return null;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
propertyContainsMany(propName, desc, manyWhereJoin);
@@ -21,16 +21,6 @@ final class AllEqualsExpression extends NonPrepareExpression {
return propName;
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.writeAllEquals(propMap);
}
@Override
public String nestedPath(BeanDescriptor<?> desc) {
return null;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
if (propMap != null) {
@@ -23,23 +23,6 @@ final class ArrayContainsExpression extends AbstractExpression {
}
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
if (values.length == 1) {
context.writeEqualTo(propName, values[0]);
} else {
if (contains) {
context.startBoolMust();
} else {
context.startBoolMustNot();
}
for (Object value : values) {
context.writeEqualTo(propName, value);
}
context.endBool();
}
}
@Override
public void queryPlanHash(StringBuilder builder) {
builder.append("ArrayContains[").append(propName)
@@ -4,8 +4,6 @@ import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import java.io.IOException;
/**
* IsEmpty expression for ARRAY type.
*/
@@ -18,11 +16,6 @@ final class ArrayIsEmptyExpression extends AbstractExpression {
this.empty = empty;
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.writeExists(!empty, propName);
}
@Override
public void queryPlanHash(StringBuilder builder) {
if (empty) {
@@ -5,8 +5,6 @@ import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
import java.io.IOException;
final class BetweenExpression extends AbstractExpression {
private static final String _BETWEEN = " between ? and ?";
@@ -28,11 +26,6 @@ final class BetweenExpression extends AbstractExpression {
return NamedParamHelp.value(valueHigh);
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.writeRange(propName, Op.GT_EQ, low(), Op.LT_EQ, high());
}
@Override
public void addBindValues(SpiExpressionRequest request) {
ElPropertyValue prop = getElProp(request);

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