Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Support for query-by-example across all the GORM implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed Feb 7, 2011
1 parent 9968b73 commit 2b898b0
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 33 deletions.
Expand Up @@ -9,5 +9,8 @@ class Plant implements Serializable{
boolean goesInPatch
String name


static mapping = {
name index:true
goesInPatch index:true
}
}
@@ -0,0 +1,54 @@
package grails.gorm.tests

class FindByExampleSpec extends GormDatastoreSpec{

def "Test findAll by example"() {
given:
new Plant(name:"Pineapple", goesInPatch:false).save()
new Plant(name:"Cabbage", goesInPatch:true).save()
new Plant(name:"Kiwi", goesInPatch:false).save(flush:true)
session.clear()
when:
def results = Plant.findAll(new Plant(goesInPatch:false))
then:
results.size() == 2
"Pineapple" in results*.name
"Kiwi" in results*.name

when:
results = Plant.findAll(new Plant(name:"Cabbage",goesInPatch:false))

then:
results.size() == 0

when:
results = Plant.findAll(new Plant(name:"Cabbage",goesInPatch:true))

then:
results.size() == 1
"Cabbage" in results*.name

}


def "Test find by example"() {
given:
new Plant(name:"Pineapple", goesInPatch:false).save()
new Plant(name:"Cabbage", goesInPatch:true).save()
new Plant(name:"Kiwi", goesInPatch:false).save(flush:true)
session.clear()

when:
Plant result = Plant.find(new Plant(name:"Cabbage",goesInPatch:false))

then:
result == null

when:
result = Plant.find(new Plant(name:"Cabbage",goesInPatch:true))

then:
result != null
result.name == "Cabbage"
}
}
Expand Up @@ -1017,6 +1017,10 @@ class Plant implements Serializable{
boolean goesInPatch
String name
static mapping = {
name index:true
goesInPatch index:true
}
}
Expand Down
@@ -1,3 +1,4 @@

/* Copyright (C) 2010 SpringSource
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -21,6 +22,8 @@ import org.springframework.beans.BeanWrapperImpl
import org.springframework.datastore.mapping.core.Datastore
import org.springframework.datastore.mapping.core.Session
import org.springframework.datastore.mapping.query.Query
import org.springframework.datastore.mapping.model.types.Association;
import org.springframework.datastore.mapping.model.PersistentProperty;



Expand Down Expand Up @@ -213,38 +216,134 @@ class GormStaticApi extends AbstractGormApi {
.createQuery(persistentClass)
.list()
}

/**
* Finds all results matching all of the given conditions. Eg. Book.findAllWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @return A list of results
* The same as {@link #list()}
*
* @return The list of all entities
*/
List findAllWhere(Map queryMap) {
Query q = datastore.currentSession.createQuery(persistentClass)
if(queryMap) {
for(entry in queryMap) {
q.eq(entry.key, entry.value)
}
}
q.list()
List findAll() {
list()
}

/**
* Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @return A single result
* Finds an object by example
*
* @param example The example
* @return A list of matching results
*/
def findWhere(Map queryMap) {
Query q = datastore.currentSession.createQuery(persistentClass)
if(queryMap) {
for(entry in queryMap) {
q.eq(entry.key, entry.value)
}
}
q.singleResult()
List findAll(Object example) {
findAll(example, Collections.emptyMap())
}

/**
* Finds an object by example using the given arguments for pagination
*
* @param example The example
* @param args The arguments
*
* @return A list of matching results
*/
List findAll(Object example, Map args) {
if(persistentEntity.isInstance(example)) {
def queryMap = createQueryMapForExample(persistentEntity, example)
return findAllWhere(queryMap, args)
}
return Collections.emptyList()
}

private Map createQueryMapForExample(org.springframework.datastore.mapping.model.PersistentEntity persistentEntity, example) {
def props = persistentEntity.persistentProperties.findAll { PersistentProperty prop ->
!(prop instanceof Association)
}

def queryMap = [:]
for(PersistentProperty prop in props) {
def val = example[prop.name]
if(val != null)
queryMap[prop.name] = val
}
return queryMap
}

/**
* Finds all results matching all of the given conditions. Eg. Book.findAllWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @return A list of results
*/
List findAllWhere(Map queryMap) {
findAllWhere(queryMap, Collections.emptyMap())
}

/**
* Finds all results matching all of the given conditions. Eg. Book.findAllWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @param args The Query arguments
*
* @return A list of results
*/
List findAllWhere(Map queryMap, Map args) {
Query q = datastore.currentSession.createQuery(persistentClass)
q.allEq(queryMap)
DynamicFinder.populateArgumentsForCriteria persistentClass, q, args
q.list()
}


/**
* Finds an object by example
*
* @param example The example
* @return A list of matching results
*/
def find(Object example) {
find(example, Collections.emptyMap())
}

/**
* Finds an object by example using the given arguments for pagination
*
* @param example The example
* @param args The arguments
*
* @return A list of matching results
*/
def find(Object example, Map args) {
if(persistentEntity.isInstance(example)) {
def queryMap = createQueryMapForExample(persistentEntity, example)
return findWhere(queryMap, args)
}
return null
}

/**
* Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @return A single result
*/
def findWhere(Map queryMap) {
findWhere(queryMap, Collections.emptyMap())
}

/**
* Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand")
*
* @param queryMap The map of conditions
* @param args The Query arguments
*
* @return A single result
*/
def findWhere(Map queryMap, Map args) {
Query q = datastore.currentSession.createQuery(persistentClass)
if(queryMap) {
q.allEq(queryMap)
}
DynamicFinder.populateArgumentsForCriteria persistentClass, q, args
q.singleResult()
}

/**
* Execute a closure whose first argument is a reference to the current session
Expand Down
Expand Up @@ -14,6 +14,14 @@
*/
package org.springframework.datastore.mapping.query;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.persistence.FlushModeType;

import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.datastore.mapping.core.AbstractDatastore;
import org.springframework.datastore.mapping.core.Session;
Expand All @@ -24,12 +32,6 @@
import org.springframework.datastore.mapping.model.types.Association;
import org.springframework.util.Assert;

import javax.persistence.FlushModeType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
* Models a query that can be executed against a data store
*
Expand Down Expand Up @@ -232,6 +234,19 @@ public Query eq(String property, Object value) {
criteria.add(Restrictions.eq(property, value));
return this;
}

/**
* Shortcut to restrict the query to multiple given property values
*
* @param values The values
* @return This query instance
*/
public Query allEq(Map<String, Object> values) {
for (String property : values.keySet()) {
eq(property, values.get(property));
}
return this;
}

/**
* Used to restrict a value to be empty (such as a blank string or an empty collection)
Expand Down

0 comments on commit 2b898b0

Please sign in to comment.