grails.gorm.DetachedCriteria.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grails-datastore-gorm Show documentation
Show all versions of grails-datastore-gorm Show documentation
GORM - Grails Data Access Framework
/* Copyright (C) 2011 SpringSource
*
* Licensed 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 grails.gorm
import groovy.transform.CompileStatic
import groovy.transform.TypeCheckingMode
import org.grails.datastore.gorm.GormEnhancer
import org.grails.datastore.gorm.GormStaticApi
import org.grails.datastore.gorm.finders.DynamicFinder
import org.grails.datastore.gorm.query.GormOperations
import org.grails.datastore.gorm.query.criteria.AbstractDetachedCriteria
import org.grails.datastore.mapping.core.Session
import org.grails.datastore.mapping.query.Query
import org.grails.datastore.mapping.query.api.Criteria
import org.grails.datastore.mapping.query.api.ProjectionList
import org.grails.datastore.mapping.query.api.QueryAliasAwareSession
import org.grails.datastore.mapping.query.api.QueryArgumentsAware
import org.grails.datastore.mapping.query.api.QueryableCriteria
import javax.persistence.criteria.JoinType
/**
* Represents criteria that is not bound to the current connection and can be built up and re-used at a later date.
*
* @author Graeme Rocher
* @since 1.0
*/
@CompileStatic
class DetachedCriteria extends AbstractDetachedCriteria implements GormOperations, QueryableCriteria, Iterable {
/**
* Constructs a DetachedCriteria instance target the given class and alias for the name
* @param targetClass The target class
* @param alias The root alias to be used in queries
*/
DetachedCriteria(Class targetClass, String alias = null) {
super(targetClass, alias)
}
/**
* Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one.
*
* @param additionalQuery The additional query
* @return A new query
*/
@Override
DetachedCriteria where(@DelegatesTo(DetachedCriteria) Closure additionalQuery) {
DetachedCriteria newQuery = clone()
return newQuery.build(additionalQuery)
}
@Override
DetachedCriteria withConnection(String name) {
return (DetachedCriteria)super.withConnection(name)
}
/**
* Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one.
*
* @param additionalQuery The additional query
* @return A new query
*/
@Override
DetachedCriteria whereLazy(@DelegatesTo(DetachedCriteria) Closure additionalQuery) {
DetachedCriteria newQuery = clone()
return newQuery.build(additionalQuery)
}
/**
* Synonym for #get
*/
T find(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) {
get(args, additionalCriteria)
}
/**
* Defines projections.
*
* @param callable The callable
* @return This detached criteria
*/
DetachedCriteria projections(@DelegatesTo(ProjectionList) Closure callable) {
callable.delegate = projectionList
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable.call()
return this
}
/**
* Synonym for #get
*/
T find(@DelegatesTo(DetachedCriteria) Closure additionalCriteria) {
get(Collections.emptyMap(), additionalCriteria)
}
/**
* Returns a single result matching the criterion contained within this DetachedCriteria instance
*
* @return A single entity
*/
T get(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) {
(T)withPopulatedQuery(args, additionalCriteria) { Query query ->
query.singleResult()
}
}
/**
* Returns a single result matching the criterion contained within this DetachedCriteria instance
*
* @return A single entity
*/
T get(@DelegatesTo(DetachedCriteria) Closure additionalCriteria) {
get(Collections.emptyMap(), additionalCriteria)
}
/**
* Lists all records matching the criterion contained within this DetachedCriteria instance
*
* @return A list of matching instances
*/
List list(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) {
(List)withPopulatedQuery(args, additionalCriteria) { Query query ->
if (args?.max) {
return new PagedResultList(query)
}
return query.list()
}
}
/**
* Lists all records matching the criterion contained within this DetachedCriteria instance
*
* @return A list of matching instances
*/
List list(@DelegatesTo(DetachedCriteria) Closure additionalCriteria) {
list(Collections.emptyMap(), additionalCriteria)
}
@Override
Iterator iterator() {
return list().iterator()
}
@Override
DetachedCriteria join(String property) {
return (DetachedCriteria)super.join(property)
}
@Override
DetachedCriteria join(String property, JoinType joinType) {
return (DetachedCriteria)super.join(property, joinType)
}
@Override
DetachedCriteria select(String property) {
return (DetachedCriteria)super.select(property)
}
@Override
DetachedCriteria and(@DelegatesTo(AbstractDetachedCriteria) Closure callable) {
return (DetachedCriteria)super.and(callable)
}
@Override
DetachedCriteria or(@DelegatesTo(AbstractDetachedCriteria) Closure callable) {
return (DetachedCriteria)super.or(callable)
}
@Override
DetachedCriteria not(@DelegatesTo(AbstractDetachedCriteria) Closure callable) {
return (DetachedCriteria)super.not(callable)
}
@Override
DetachedCriteria "in"(String propertyName, Collection values) {
return (DetachedCriteria)super.in(propertyName, values)
}
@Override
DetachedCriteria "in"(String propertyName, QueryableCriteria subquery) {
return (DetachedCriteria)super.in(propertyName, subquery)
}
@Override
DetachedCriteria inList(String propertyName, QueryableCriteria subquery) {
return (DetachedCriteria)super.inList(propertyName, subquery)
}
@Override
DetachedCriteria "in"(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) {
return (DetachedCriteria)super.in(propertyName, subquery)
}
@Override
DetachedCriteria inList(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) {
return (DetachedCriteria)super.inList(propertyName, subquery)
}
@Override
DetachedCriteria "in"(String propertyName, Object[] values) {
return (DetachedCriteria)super.in(propertyName, values)
}
@Override
DetachedCriteria notIn(String propertyName, QueryableCriteria subquery) {
return (DetachedCriteria)super.notIn(propertyName, subquery)
}
@Override
DetachedCriteria notIn(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) {
return (DetachedCriteria)super.notIn(propertyName, subquery)
}
@Override
DetachedCriteria order(String propertyName) {
return (DetachedCriteria)super.order(propertyName)
}
@Override
DetachedCriteria order(Query.Order o) {
return (DetachedCriteria)super.order(o)
}
@Override
DetachedCriteria order(String propertyName, String direction) {
return (DetachedCriteria)super.order(propertyName, direction)
}
@Override
DetachedCriteria inList(String propertyName, Collection values) {
return (DetachedCriteria)super.inList(propertyName, values)
}
@Override
DetachedCriteria inList(String propertyName, Object[] values) {
return (DetachedCriteria)super.inList(propertyName, values)
}
@Override
DetachedCriteria sizeEq(String propertyName, int size) {
return (DetachedCriteria)super.sizeEq(propertyName, size)
}
@Override
DetachedCriteria sizeGt(String propertyName, int size) {
return (DetachedCriteria)super.sizeGt(propertyName, size)
}
@Override
DetachedCriteria sizeGe(String propertyName, int size) {
return (DetachedCriteria)super.sizeGe(propertyName, size)
}
@Override
DetachedCriteria sizeLe(String propertyName, int size) {
return (DetachedCriteria)super.sizeLe(propertyName, size)
}
@Override
DetachedCriteria sizeLt(String propertyName, int size) {
return (DetachedCriteria)super.sizeLt(propertyName, size)
}
@Override
DetachedCriteria sizeNe(String propertyName, int size) {
return (DetachedCriteria)super.sizeNe(propertyName, size)
}
@Override
DetachedCriteria eqProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.eqProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria neProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.neProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria allEq(Map propertyValues) {
return (DetachedCriteria)super.allEq(propertyValues)
}
@Override
DetachedCriteria gtProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.gtProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria geProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.geProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria ltProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.ltProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria leProperty(String propertyName, String otherPropertyName) {
return (DetachedCriteria)super.leProperty(propertyName, otherPropertyName)
}
@Override
DetachedCriteria idEquals(Object value) {
return (DetachedCriteria)super.idEquals(value)
}
@Override
DetachedCriteria exists(QueryableCriteria subquery) {
return (DetachedCriteria)super.exists(subquery)
}
@Override
DetachedCriteria notExists(QueryableCriteria subquery) {
return (DetachedCriteria)super.notExists(subquery)
}
@Override
DetachedCriteria isEmpty(String propertyName) {
return (DetachedCriteria)super.isEmpty(propertyName)
}
@Override
DetachedCriteria isNotEmpty(String propertyName) {
return (DetachedCriteria)super.isNotEmpty(propertyName)
}
@Override
DetachedCriteria isNull(String propertyName) {
return (DetachedCriteria)super.isNull(propertyName)
}
@Override
DetachedCriteria isNotNull(String propertyName) {
return (DetachedCriteria)super.isNotNull(propertyName)
}
@Override
DetachedCriteria eq(String propertyName, Object propertyValue) {
return (DetachedCriteria)super.eq(propertyName, propertyValue)
}
@Override
DetachedCriteria idEq(Object propertyValue) {
return (DetachedCriteria)super.idEq(propertyValue)
}
@Override
DetachedCriteria ne(String propertyName, Object propertyValue) {
return (DetachedCriteria)super.ne(propertyName, propertyValue)
}
@Override
DetachedCriteria between(String propertyName, Object start, Object finish) {
return (DetachedCriteria)super.between(propertyName, start, finish)
}
@Override
DetachedCriteria gte(String property, Object value) {
return (DetachedCriteria)super.gte(property, value)
}
@Override
DetachedCriteria ge(String property, Object value) {
return (DetachedCriteria)super.ge(property, value)
}
@Override
DetachedCriteria gt(String property, Object value) {
return (DetachedCriteria)super.gt(property, value)
}
@Override
DetachedCriteria lte(String property, Object value) {
return (DetachedCriteria)super.lte(property, value)
}
@Override
DetachedCriteria le(String property, Object value) {
return (DetachedCriteria)super.le(property, value)
}
@Override
DetachedCriteria lt(String property, Object value) {
return (DetachedCriteria)super.lt(property, value)
}
@Override
DetachedCriteria like(String propertyName, Object propertyValue) {
return (DetachedCriteria)super.like(propertyName, propertyValue)
}
@Override
DetachedCriteria ilike(String propertyName, Object propertyValue) {
return (DetachedCriteria)super.ilike(propertyName, propertyValue)
}
@Override
DetachedCriteria rlike(String propertyName, Object propertyValue) {
return (DetachedCriteria)super.rlike(propertyName, propertyValue)
}
@Override
DetachedCriteria eqAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.eqAll(propertyName, propertyValue)
}
@Override
DetachedCriteria gtAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.gtAll(propertyName, propertyValue)
}
@Override
DetachedCriteria ltAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.ltAll(propertyName, propertyValue)
}
@Override
DetachedCriteria geAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.geAll(propertyName, propertyValue)
}
@Override
DetachedCriteria leAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.leAll(propertyName, propertyValue)
}
@Override
DetachedCriteria eqAll(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.eqAll(propertyName, propertyValue)
}
@Override
DetachedCriteria gtAll(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.gtAll(propertyName, propertyValue)
}
@Override
DetachedCriteria gtSome(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.gtSome(propertyName, propertyValue)
}
@Override
DetachedCriteria gtSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.gtSome(propertyName, propertyValue)
}
@Override
DetachedCriteria geSome(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.geSome(propertyName, propertyValue)
}
@Override
DetachedCriteria geSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.geSome(propertyName, propertyValue)
}
@Override
DetachedCriteria ltSome(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.ltSome(propertyName, propertyValue)
}
@Override
DetachedCriteria ltSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.ltSome(propertyName, propertyValue)
}
@Override
DetachedCriteria leSome(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.leSome(propertyName, propertyValue)
}
@Override
DetachedCriteria leSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) {
return (DetachedCriteria)super.leSome(propertyName, propertyValue)
}
@Override
DetachedCriteria ltAll(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.ltAll(propertyName, propertyValue)
}
@Override
DetachedCriteria geAll(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.geAll(propertyName, propertyValue)
}
@Override
DetachedCriteria leAll(String propertyName, QueryableCriteria propertyValue) {
return (DetachedCriteria)super.leAll(propertyName, propertyValue)
}
/**
* Counts the number of records returned by the query
*
* @param args The arguments
* @return The count
*/
Number count(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) {
(Number)withPopulatedQuery(args, additionalCriteria) { Query query ->
query.projections().count()
query.singleResult()
}
}
/**
* Counts the number of records returned by the query
*
* @param args The arguments
* @return The count
*/
Number count(@DelegatesTo(DetachedCriteria) Closure additionalCriteria) {
(Number)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query ->
query.projections().count()
query.singleResult()
}
}
/**
* Synonym for #count()
*/
Number size() {
count()
}
/**
* Counts the number of records returned by the query
*
* @param args The arguments
* @return The count
*/
boolean asBoolean(@DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) {
(Boolean)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query ->
query.projections().count()
((Number)query.singleResult()) > 0
}
}
/**
* Deletes all entities matching this criteria
*
* @return The total number deleted
*/
Number deleteAll() {
GormEnhancer.findStaticApi(targetClass, connectionName).withDatastoreSession { Session session ->
session.deleteAll(this)
}
}
/**
* Updates all entities matching this criteria
*
* @return The total number updated
*/
Number updateAll(Map properties) {
GormEnhancer.findStaticApi(targetClass, connectionName).withDatastoreSession { Session session ->
session.updateAll(this, properties)
}
}
/**
* Enable the builder syntax for constructing Criteria
*
* @param callable The callable closure
* @return A new criteria instance
*/
@Override
DetachedCriteria build(@DelegatesTo(DetachedCriteria) Closure callable) {
(DetachedCriteria)super.build(callable)
}
/**
* Enable the builder syntax for constructing Criteria
*
* @param callable The callable closure
* @return A new criteria instance
*/
@Override
DetachedCriteria buildLazy(@DelegatesTo(DetachedCriteria) Closure callable) {
(DetachedCriteria)super.buildLazy(callable)
}
/**
* Sets the default max to use and returns a new criteria instance. This method does not mutate the original criteria!
*
* @param max The max to use
* @return A new DetachedCriteria instance derived from this
*/
@Override
DetachedCriteria max(int max) {
(DetachedCriteria)super.max(max)
}
/**
* Sets the default offset to use and returns a new criteria instance. This method does not mutate the original criteria!
*
* @param offset The offset to use
* @return A new DetachedCriteria instance derived from this
*/
@Override
DetachedCriteria offset(int offset) {
(DetachedCriteria)super.offset(offset)
}
/**
* Adds a sort order to this criteria instance
*
* @param property The property to sort by
* @return This criteria instance
*/
DetachedCriteria sort(String property) {
(DetachedCriteria)super.sort(property)
}
/**
* Adds a sort order to this criteria instance
*
* @param property The property to sort by
* @param direction The direction to sort by
* @return This criteria instance
*/
DetachedCriteria sort(String property, String direction) {
(DetachedCriteria)super.sort(property,direction)
}
/**
* Adds a property projection
*
* @param property The property to project
* @return This criteria instance
*/
DetachedCriteria property(String property) {
(DetachedCriteria)super.property(property)
}
/**
* Adds an id projection
*
* @param property The property to project
* @return This criteria instance
*/
DetachedCriteria id() {
(DetachedCriteria)super.id()
}
/**
* Adds a avg projection
*
* @param property The property to avg by
* @return This criteria instance
*/
DetachedCriteria avg(String property) {
(DetachedCriteria)super.avg(property)
}
/**
* Adds a sum projection
*
* @param property The property to sum by
* @return This criteria instance
*/
DetachedCriteria sum(String property) {
(DetachedCriteria)super.sum(property)
}
/**
* Adds a sum projection
*
* @param property The property to min by
* @return This criteria instance
*/
DetachedCriteria min(String property) {
(DetachedCriteria)super.min(property)
}
/**
* Adds a min projection
*
* @param property The property to max by
* @return This criteria instance
*/
DetachedCriteria max(String property) {
(DetachedCriteria)super.max(property)
}
/**
* Adds a distinct property projection
*
* @param property The property to obtain the distinct value for
* @return This criteria instance
*/
DetachedCriteria distinct(String property) {
(DetachedCriteria)super.distinct(property)
}
@Override
protected DetachedCriteria newInstance() {
new DetachedCriteria(targetClass, alias)
}
@Override
protected DetachedCriteria clone() {
return (DetachedCriteria)super.clone()
}
protected void handleJunction(Closure callable) {
try {
callable.delegate = this
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable.call()
}
finally {
def lastJunction = junctions.remove(junctions.size() - 1)
add lastJunction
}
}
protected QueryableCriteria buildQueryableCriteria(Closure queryClosure) {
return new DetachedCriteria(targetClass).build(queryClosure)
}
private withPopulatedQuery(Map args, Closure additionalCriteria, Closure callable) {
GormStaticApi staticApi = persistentEntity.isMultiTenant() ? GormEnhancer.findStaticApi(targetClass) : GormEnhancer.findStaticApi(targetClass, connectionName)
staticApi.withDatastoreSession { Session session ->
applyLazyCriteria()
Query query
if(alias && (session instanceof QueryAliasAwareSession)) {
query = session.createQuery(targetClass, alias)
}
else {
query = session.createQuery(targetClass)
}
if (defaultMax != null) {
query.max(defaultMax)
}
if (defaultOffset != null) {
query.offset(defaultOffset)
}
DynamicFinder.applyDetachedCriteria(query, this)
if(query instanceof QueryArgumentsAware) {
((QueryArgumentsAware)query).arguments = args
}
if (additionalCriteria != null) {
def additionalDetached = new DetachedCriteria(targetClass).build(additionalCriteria)
DynamicFinder.applyDetachedCriteria(query, additionalDetached)
}
DynamicFinder.populateArgumentsForCriteria(targetClass, query, args)
callable.call(query)
}
}
protected void applyLazyCriteria() {
if (lazyQuery == null) {
return
}
def criteria = lazyQuery
lazyQuery = null
this.with criteria
}
}