ofbiz-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Pranay Pandey <pranay.pan...@hotwaxmedia.com>
Subject Re: svn commit: r1627940 - /ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java
Date Tue, 30 Sep 2014 10:45:20 GMT

+1

Thanks Scott.

Pranay Pandey
HotWax Media
http://www.hotwaxmedia.com



On Sep 27, 2014, at 3:29 PM, Jacopo Cappellato <jacopo.cappellato@hotwaxmedia.com> wrote:

> This is really an amazing contribution! Thank you Scott.
> 
> Jacopo
> 
> On Sep 27, 2014, at 11:22 AM, lektran@apache.org wrote:
> 
>> Author: lektran
>> Date: Sat Sep 27 09:22:31 2014
>> New Revision: 1627940
>> 
>> URL: http://svn.apache.org/r1627940
>> Log:
>> OFBIZ-4053 Implement an entity query builder to be used as a friendlier API for executing
entity queries.
>> 
>> Entry point is the static EntityQuery.use(Delegator) method which will then return
an EntityQuery instance whose methods support method chaining to set query options.
>> The query can then be executed using the first(), list(), iterator() and one() methods
which respectively return:
>> - The first result from a result set
>> - The full list of results from a result set
>> - An EntityListIterator to iterate over a result set
>> - The single record from a query that will return only one record (such as a lookup
by primary key)
>> 
>> Added:
>>   ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java   (with
props)
>> 
>> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java?rev=1627940&view=auto
>> ==============================================================================
>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java (added)
>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java Sat Sep
27 09:22:31 2014
>> @@ -0,0 +1,416 @@
>> +/*******************************************************************************
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements.  See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership.  The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License.  You may obtain a copy of the License at
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing,
>> + * software distributed under the License is distributed on an
>> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>> + * KIND, either express or implied.  See the License for the
>> + * specific language governing permissions and limitations
>> + * under the License.
>> + *******************************************************************************/
>> +package org.ofbiz.entity.util;
>> +
>> +import java.sql.Timestamp;
>> +import java.util.Arrays;
>> +import java.util.List;
>> +import java.util.Map;
>> +import java.util.Set;
>> +
>> +import org.ofbiz.base.util.Debug;
>> +import org.ofbiz.base.util.UtilMisc;
>> +import org.ofbiz.entity.Delegator;
>> +import org.ofbiz.entity.GenericEntityException;
>> +import org.ofbiz.entity.GenericValue;
>> +import org.ofbiz.entity.condition.EntityCondition;
>> +import org.ofbiz.entity.model.DynamicViewEntity;
>> +import org.ofbiz.entity.util.EntityFindOptions;
>> +import org.ofbiz.entity.util.EntityListIterator;
>> +import org.ofbiz.entity.util.EntityUtil;
>> +
>> +/**
>> + * Used to setup various options for and subsequently execute entity queries.
>> + *
>> + * All methods to set options modify the EntityQuery instance then return this modified
object to allow method call chaining. It is
>> + * important to note that this object is not immutable and is modified internally,
and returning EntityQuery is just a
>> + * self reference for convenience.
>> + *
>> + * After a query the object can be further modified and then used to perform another
query if desired.
>> + */
>> +public class EntityQuery {
>> +
>> +    public static final String module = EntityQuery.class.getName();
>> +
>> +    private Delegator delegator;
>> +    private String entityName = null;
>> +    private DynamicViewEntity dynamicViewEntity = null;
>> +    private boolean useCache = false;
>> +    private EntityCondition whereEntityCondition = null;
>> +    private Set<String> fieldsToSelect = null;
>> +    private List<String> orderBy = null;
>> +    private Integer resultSetType = EntityFindOptions.TYPE_FORWARD_ONLY;
>> +    private Integer fetchSize = null;
>> +    private Integer maxRows = null;
>> +    private Boolean distinct = null;
>> +    private EntityCondition havingEntityCondition = null;
>> +    private boolean filterByDate = false;
>> +    private Timestamp filterByDateMoment;
>> +
>> +
>> +
>> +    /** Construct an EntityQuery object for use against the specified Delegator
>> +     * @param delegator - The delegator instance to use for the query
>> +     * @return Returns a new EntityQuery object
>> +     */
>> +    public static EntityQuery use(Delegator delegator) {
>> +        return new EntityQuery(delegator);
>> +    }
>> +
>> +    /** Construct an EntityQuery object for use against the specified Delegator
>> +     * @param delegator - The delegator instance to use for the query
>> +     * @return Returns a new EntityQuery object
>> +     */
>> +    public EntityQuery(Delegator delegator) {
>> +        this.delegator = delegator;
>> +    }
>> +
>> +    /** Set the fields to be returned when the query is executed.
>> +     * 
>> +     * Note that the select methods are not additive, if a subsequent 
>> +     * call is made to select then the existing fields for selection 
>> +     * will be replaced.
>> +     * @param fieldsToSelect - A Set of Strings containing the field names to be
selected
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery select(Set<String> fieldsToSelect) {
>> +        this.fieldsToSelect = fieldsToSelect;
>> +        return this;
>> +    }
>> +
>> +    /** Set the fields to be returned when the query is executed.
>> +     * 
>> +     * Note that the select methods are not additive, if a subsequent 
>> +     * call is made to select then the existing fields for selection 
>> +     * will be replaced.
>> +     * @param fieldsToSelect - Strings containing the field names to be selected
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery select(String...fields) {
>> +        this.fieldsToSelect = UtilMisc.toSetArray(fields);
>> +        return this;
>> +    }
>> +
>> +    /** Set the entity to query against
>> +     * @param entityName - The name of the entity to query against
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery from(String entityName) {
>> +        this.entityName = entityName;
>> +        this.dynamicViewEntity = null;
>> +        return this;
>> +    }
>> +
>> +    /** Set the entity to query against
>> +     * @param dynamicViewEntity - The DynamicViewEntity object to query against
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery from(DynamicViewEntity dynamicViewEntity) {
>> +        this.dynamicViewEntity  = dynamicViewEntity;
>> +        this.entityName = null;
>> +        return this;
>> +    }
>> +
>> +    /** Set the EntityCondition to be used as the WHERE clause for the query
>> +     * 
>> +     * NOTE: Each successive call to any of the where(...) methods will replace
the currently set condition for the query.
>> +     * @param entityCondition - An EntityCondition object to be used as the where
clause for this query
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery where(EntityCondition entityCondition) {
>> +        this.whereEntityCondition = entityCondition;
>> +        return this;
>> +    }
>> +
>> +    /** Set a Map of field name/values to be ANDed together as the WHERE clause
for the query
>> +     * 
>> +     * NOTE: Each successive call to any of the where(...) methods will replace
the currently set condition for the query.
>> +     * @param fieldMap - A Map of field names/values to be ANDed together as the
where clause for the query
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery where(Map<String, Object> fieldMap) {
>> +        this.whereEntityCondition = EntityCondition.makeCondition(fieldMap);
>> +        return this;
>> +    }
>> +
>> +    /** Set a series of field name/values to be ANDed together as the WHERE clause
for the query
>> +     * 
>> +     * NOTE: Each successive call to any of the where(...) methods will replace
the currently set condition for the query.
>> +     * @param fieldMap - A series of field names/values to be ANDed together as
the where clause for the query
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery where(Object...fields) {
>> +        this.whereEntityCondition = EntityCondition.makeCondition(UtilMisc.toMap(fields));
>> +        return this;
>> +    }
>> +
>> +    /** Set a list of EntityCondition objects to be ANDed together as the WHERE
clause for the query
>> +     * 
>> +     * NOTE: Each successive call to any of the where(...) methods will replace
the currently set condition for the query.
>> +     * @param fieldMap - A list of EntityCondition objects to be ANDed together
as the WHERE clause for the query
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery where(List<EntityCondition> andConditions) {
>> +        this.whereEntityCondition = EntityCondition.makeCondition(andConditions);
>> +        return this;
>> +    }
>> +
>> +    /** Set the EntityCondition to be used as the HAVING clause for the query.
>> +     * 
>> +     * NOTE: Each successive call to any of the having(...) methods will replace
the currently set condition for the query.
>> +     * @param entityCondition - The EntityCondition object that specifies how to
constrain
>> +     *            this query after any groupings are done (if this is a view
>> +     *            entity with group-by aliases)
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery having(EntityCondition entityCondition) {
>> +        this.havingEntityCondition = entityCondition;
>> +        return this;
>> +    }
>> +
>> +    /** The fields of the named entity to order the resultset by; optionally add
a " ASC" for ascending or " DESC" for descending
>> +     * 
>> +     * NOTE: Each successive call to any of the orderBy(...) methods will replace
the currently set orderBy fields for the query.
>> +     * @param orderBy - The fields of the named entity to order the resultset by
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery orderBy(List<String> orderBy) {
>> +        this.orderBy = orderBy;
>> +        return this;
>> +    }
>> +
>> +    /** The fields of the named entity to order the resultset by; optionally add
a " ASC" for ascending or " DESC" for descending
>> +     * 
>> +     * NOTE: Each successive call to any of the orderBy(...) methods will replace
the currently set orderBy fields for the query.
>> +     * @param orderBy - The fields of the named entity to order the resultset by
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery orderBy(String...fields) {
>> +        this.orderBy = Arrays.asList(fields);
>> +        return this;
>> +    }
>> +
>> +    /** Indicate that the ResultSet object's cursor may move only forward (this
is the default behavior)
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery cursorForwardOnly() {
>> +        this.resultSetType = EntityFindOptions.TYPE_FORWARD_ONLY;
>> +        return this;
>> +    }
>> +
>> +    /** Indicate that the ResultSet object's cursor is scrollable but generally
sensitive to changes to the data that underlies the ResultSet.
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery cursorScrollSensitive() {
>> +        this.resultSetType = EntityFindOptions.TYPE_SCROLL_SENSITIVE;
>> +        return this;
>> +    }
>> +
>> +    /** Indicate that the ResultSet object's cursor is scrollable but generally
not sensitive to changes to the data that underlies the ResultSet.
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery cursorScrollInsensitive() {
>> +        this.resultSetType = EntityFindOptions.TYPE_SCROLL_INSENSITIVE;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies the fetch size for this query. -1 will fall back to datasource
settings.
>> +     * 
>> +     * @param fetchSize - The fetch size for this query
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery fetchSize(int fetchSize) {
>> +        this.fetchSize = fetchSize;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies the max number of rows to return, 0 means all rows.
>> +     * 
>> +     * @param maxRows - the max number of rows to return
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery maxRows(int maxRows) {
>> +        this.maxRows = maxRows;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies that the values returned should be filtered to remove duplicate
values.
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery distinct() {
>> +        this.distinct = true;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies whether the values returned should be filtered to remove duplicate
values.
>> +     * 
>> +     * @param distinct - boolean indicating whether the values returned should be
filtered to remove duplicate values
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery distinct(boolean distinct) {
>> +        this.distinct = distinct;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies whether results should be read from the cache (or written to the
cache if the results have not yet been cached)
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery cache() {
>> +        this.useCache = true;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies whether the query should return only values that are currently
active using from/thruDate fields.
>> +     * 
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery filterByDate() {
>> +        this.filterByDate  = true;
>> +        this.filterByDateMoment = null;
>> +        return this;
>> +    }
>> +
>> +    /** Specifies whether the query should return only values that are active during
the specified moment using from/thruDate fields.
>> +     * 
>> +     * @param moment - Timestamp representing the moment in time that the values
should be active during
>> +     * @return this EntityQuery object, to enable chaining
>> +     */
>> +    public EntityQuery filterByDate(Timestamp moment) {
>> +        this.filterByDate = true;
>> +        this.filterByDateMoment = moment;
>> +        return this;
>> +    }
>> +
>> +    /** Executes the EntityQuery and returns a list of results
>> +     * 
>> +     * @return Returns a List of GenericValues representing the results of the query
>> +     */
>> +    public List<GenericValue> queryList() throws GenericEntityException {
>> +        return query(null);
>> +    }
>> +
>> +    /** Executes the EntityQuery and returns an EntityListIterator representing
the result of the query. 
>> +     * 
>> +     * NOTE:  THAT THIS MUST BE CLOSED (preferably in a finally block) WHEN YOU
>> +     *        ARE DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT
>> +     *        WILL MAINTAIN A DATABASE CONNECTION.
>> +     * 
>> +     * @return Returns an EntityListIterator representing the result of the query
>> +     */
>> +    public EntityListIterator queryIterator() throws GenericEntityException {
>> +        if (useCache) {
>> +            Debug.logWarning("Call to iterator() with cache, ignoring cache", module);
>> +        }
>> +        if (dynamicViewEntity == null) {
>> +            return delegator.find(entityName, makeWhereCondition(false), havingEntityCondition,
fieldsToSelect, orderBy, makeEntityFindOptions());
>> +        } else {
>> +            return delegator.findListIteratorByCondition(dynamicViewEntity, makeWhereCondition(false),
havingEntityCondition, fieldsToSelect, orderBy, makeEntityFindOptions());
>> +        }
>> +    }
>> +
>> +    /** Executes the EntityQuery and returns the first result
>> +     * 
>> +     * @return GenericValue representing the first result record from the query
>> +     */
>> +    public GenericValue queryFirst() throws GenericEntityException {
>> +        EntityFindOptions efo = makeEntityFindOptions();
>> +        efo.setMaxRows(1);
>> +        GenericValue result =  EntityUtil.getFirst(query(efo));
>> +        return result;
>> +    }
>> +
>> +    /** Executes the EntityQuery and a single result record
>> +     * 
>> +     * @return GenericValue representing the only result record from the query
>> +     */
>> +    public GenericValue queryOne() throws GenericEntityException {
>> +        GenericValue result =  EntityUtil.getOnly(queryList());
>> +        return result;
>> +    }
>> +
>> +    /** Executes the EntityQuery and returns the result count
>> +     * 
>> +     * If the query generates more than a single result then an exception is thrown
>> +     * 
>> +     * @return GenericValue representing the only result record from the query
>> +     */
>> +    public long queryCount() throws GenericEntityException {
>> +        if (dynamicViewEntity != null) {
>> +            return queryIterator().getResultsSizeAfterPartialList();
>> +        }
>> +        return delegator.findCountByCondition(entityName, makeWhereCondition(false),
havingEntityCondition, makeEntityFindOptions());
>> +    }
>> +
>> +    private List<GenericValue> query(EntityFindOptions efo) throws GenericEntityException
{
>> +        EntityFindOptions findOptions = null;
>> +        if (efo == null) {
>> +            findOptions = makeEntityFindOptions();
>> +        } else {
>> +            findOptions = efo;
>> +        }
>> +        List<GenericValue> result = null;
>> +        if (dynamicViewEntity == null) {
>> +            result = delegator.findList(entityName, makeWhereCondition(useCache),
fieldsToSelect, orderBy, findOptions, useCache);
>> +        } else {
>> +            result = queryIterator().getCompleteList();
>> +        }
>> +        if (filterByDate && useCache) {
>> +            if (filterByDateMoment == null) {
>> +                return EntityUtil.filterByDate(result);
>> +            } else {
>> +                return EntityUtil.filterByDate(result, filterByDateMoment);
>> +            }
>> +        }
>> +        return result;
>> +    }
>> +
>> +    private EntityFindOptions makeEntityFindOptions() {
>> +        EntityFindOptions findOptions = new EntityFindOptions();
>> +        if (resultSetType != null) {
>> +            findOptions.setResultSetType(resultSetType);
>> +        }
>> +        if (fetchSize != null) {
>> +            findOptions.setFetchSize(fetchSize);
>> +        }
>> +        if (maxRows != null) {
>> +            findOptions.setMaxRows(maxRows);
>> +        }
>> +        if (distinct != null) {
>> +            findOptions.setDistinct(distinct);
>> +        }
>> +        return findOptions;
>> +    }
>> +
>> +    private EntityCondition makeWhereCondition(boolean usingCache) {
>> +        // we don't use the useCache field here because not all queries will actually
use the cache, e.g. findCountByCondition never uses the cache
>> +        if (filterByDate && !usingCache) {
>> +            if (filterByDateMoment == null) {
>> +                return EntityCondition.makeCondition(whereEntityCondition, EntityUtil.getFilterByDateExpr());
>> +            } else {
>> +                return EntityCondition.makeCondition(whereEntityCondition, EntityUtil.getFilterByDateExpr(filterByDateMoment));
>> +            }
>> +        }
>> +        return whereEntityCondition;
>> +    }
>> +}
>> 
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java
>> ------------------------------------------------------------------------------
>>   svn:eol-style = native
>> 
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java
>> ------------------------------------------------------------------------------
>>   svn:keywords = "Date Rev Author URL Id"
>> 
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityQuery.java
>> ------------------------------------------------------------------------------
>>   svn:mime-type = text/plain
>> 
>> 
> 


Mime
View raw message