blob: ba81f2483f6c456bc23ef696aecc9569a577f6e4 [file] [log] [blame]
/*
* Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// James Sutherland - initial API and implementation
package org.eclipse.persistence.queries;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.mappings.DatabaseMapping;
/**
* BatchFetchPolicy defines batch reading configuration.
*
* @see org.eclipse.persistence.queries.ObjectLevelReadQuery#setBatchFetchPolicy(BatchFetchPolicy)
* @author James Sutherland
*/
public class BatchFetchPolicy implements Serializable, Cloneable {
/** Define the type of batch fetching to use. */
protected BatchFetchType type;
/** Define the batch size for IN style batch fetching. */
protected int size = 500;
/** Define the attributes to be batch fetched. */
protected List<Expression> attributeExpressions;
/** Define the mapping to be batch fetched (from mapping settings). */
protected List<DatabaseMapping> batchedMappings;
/** PERF: Used internally to store the prepared mapping queries. */
protected transient Map<DatabaseMapping, ReadQuery> mappingQueries;
/** PERF: Cache the local batch read attribute names. */
protected List<String> attributes;
/** Stores temporary list of rows from parent batch query per batched mapping. */
protected transient Map<Object, List<AbstractRecord>> dataResults;
/** Stores temporary map of batched objects (this queries results). */
protected transient Map<Object, Object> batchObjects;
public BatchFetchPolicy() {
this(BatchFetchType.JOIN);
}
public BatchFetchPolicy(BatchFetchType type) {
this.type = type;
this.dataResults = new HashMap<>();
this.dataResults.put(this, new ArrayList<>());
}
@Override
public BatchFetchPolicy clone() {
BatchFetchPolicy clone = null;
try {
clone = (BatchFetchPolicy)super.clone();
} catch (CloneNotSupportedException error) {
throw new InternalError(error.getMessage());
}
if (clone.dataResults != null) {
clone.dataResults.put(clone, clone.dataResults.get(this));
}
return clone;
}
/**
* Return if using the IN fetch type.
*/
public boolean isIN() {
return this.type == BatchFetchType.IN;
}
/**
* Return if using the JOIN fetch type.
*/
public boolean isJOIN() {
return this.type == BatchFetchType.JOIN;
}
/**
* Return if using the EXISTS fetch type.
*/
public boolean isEXISTS() {
return this.type == BatchFetchType.EXISTS;
}
/**
* Return the batch fetch type, (JOIN, IN, EXISTS).
*/
public BatchFetchType getType() {
return type;
}
/**
* Set the batch fetch type, (JOIN, IN, EXISTS).
*/
public void setType(BatchFetchType type) {
this.type = type;
}
/**
* Return the batch fetch size.
*/
public int getSize() {
return size;
}
/**
* Set the batch fetch size.
*/
public void setSize(int size) {
this.size = size;
}
/**
* INTERNAL:
* PERF: Return the internally stored prepared mapping queries.
*/
public Map<DatabaseMapping, ReadQuery> getMappingQueries() {
return mappingQueries;
}
/**
* INTERNAL:
* PERF: Set the internally stored prepared mapping queries.
*/
public void setMappingQueries(Map<DatabaseMapping, ReadQuery> mappingQueries) {
this.mappingQueries = mappingQueries;
}
/**
* INTERNAL:
* PERF: Return the cached local (only) batch read attribute names.
*/
public List<String> getAttributes() {
return attributes;
}
/**
* INTERNAL:
* PERF: Set the cached local (only) batch read attribute names.
*/
public void setAttributes(List<String> attributes) {
this.attributes = attributes;
}
public void setAttributeExpressions(List<Expression> attributeExpressions) {
this.attributeExpressions = attributeExpressions;
}
/**
* INTERNAL:
* Return all attributes specified for batch reading.
*/
public List<Expression> getAttributeExpressions() {
if (this.attributeExpressions == null) {
this.attributeExpressions = new ArrayList<>();
}
return this.attributeExpressions;
}
/**
* INTERNAL:
* Return true is this query has batching
*/
public boolean hasAttributes() {
return (this.attributeExpressions != null) && (!this.attributeExpressions.isEmpty())
|| (this.batchedMappings != null);
}
/**
* INTERNAL:
* Return any mappings that are always batched.
*/
public List<DatabaseMapping> getBatchedMappings() {
return batchedMappings;
}
/**
* INTERNAL:
* Set any mappings that are always batched.
*/
public void setBatchedMappings(List<DatabaseMapping> batchedMappings) {
this.batchedMappings = batchedMappings;
}
/**
* INTERNAL:
* Return if the attribute is specified for batch reading.
*/
public boolean isAttributeBatchRead(String attributeName) {
if (this.attributeExpressions == null) {
return false;
}
List<Expression> batchReadAttributeExpressions = this.attributeExpressions;
int size = batchReadAttributeExpressions.size();
for (int index = 0; index < size; index++) {
QueryKeyExpression expression = (QueryKeyExpression)batchReadAttributeExpressions.get(index);
while (!expression.getBaseExpression().isExpressionBuilder()) {
expression = (QueryKeyExpression)expression.getBaseExpression();
}
if (expression.getName().equals(attributeName)) {
return true;
}
}
return false;
}
/**
* INTERNAL:
* Return if the attribute is specified for batch reading.
*/
public boolean isAttributeBatchRead(ClassDescriptor mappingDescriptor, String attributeName) {
if (this.attributeExpressions == null) {
return false;
}
if (this.attributes != null) {
return this.attributes.contains(attributeName);
}
return isAttributeBatchRead(attributeName);
}
/**
* INTERNAL:
* Add the row to the set of data results.
* This is used for IN batching in batches.
*/
public void addDataResults(AbstractRecord row) {
for (List<AbstractRecord> results : this.dataResults.values()) {
results.add(row);
}
}
/**
* INTERNAL:
* Return the remaining data results for the mapping.
* This is used for IN batching in batches.
*/
public List<AbstractRecord> getDataResults(DatabaseMapping mapping) {
List<AbstractRecord> result = this.dataResults.get(mapping);
if (result == null) {
result = this.dataResults.get(this);
this.dataResults.put(mapping, result);
}
return result;
}
/**
* INTERNAL:
* Set the remaining data results for the mapping.
* This is used for IN batching in batches.
*/
public void setDataResults(DatabaseMapping mapping, List<AbstractRecord> rows) {
this.dataResults.put(mapping, rows);
}
/**
* INTERNAL:
* Set the rows to the set of data results for each mapping.
* This is used for IN batching in batches.
*/
public void setDataResults(List<AbstractRecord> rows) {
this.dataResults = new HashMap<>();
this.dataResults.put(this, rows);
}
/**
* INTERNAL:
* Return temporary list of rows from parent batch query per batched mapping.
* This is used for IN batching in batches.
*/
public List<AbstractRecord> getAllDataResults() {
return this.dataResults.get(this);
}
/**
* INTERNAL:
* Return temporary list of rows from parent batch query per batched mapping.
* This is used for IN batching in batches.
*/
public Map<Object, List<AbstractRecord>> getDataResults() {
return this.dataResults;
}
/**
* INTERNAL:
* Set temporary list of rows from parent batch query per batched mapping.
* This is used for IN batching in batches.
*/
public void setDataResults(Map<Object, List<AbstractRecord>> dataResults) {
this.dataResults = dataResults;
}
/**
* INTERNAL:
* Return temporary map of batched objects.
*/
public Map<Object, Object> getBatchObjects() {
return batchObjects;
}
/**
* INTERNAL:
* Set temporary map of batched objects.
*/
public void setBatchObjects(Map<Object, Object> batchObjects) {
this.batchObjects = batchObjects;
}
}