grails findAll tag - grails

How to use "SELECT id, name, part, description FROM user " in grails findAll tag.
I tried
User.findAll("SELECT id, name, part, description FROM user")
instead using
User.findAll("FROM user")
But shows errors.
What is the tag?

finadAll() returns a Collection of domain objects, so enumerating columns to select does not make sense; the queries it understands are not real SQL, and consist basically only of WHERE clauses. Since you don't seem to want to constrain the result set, this is probably all you need:
User.findAll()
It will return a collection of all User objects. If you need constraints, the syntax ist
User.findAll("from User as u where u.id=?", [userId])
Or, even simpler, you can use a dynamic finder:
User.findAllById(userId);

If you want to run report-style queries like this, use the executeQuery method:
def rows = User.executeQuery("SELECT id, name, part, description FROM User")
The return value will be a List of Object[] where each element in the object array is the type of the column, i.e. the 1st element will be a long, 2nd a String, etc.
Note that User has to be capitalized since you're referring to the Hibernate entity - this isn't a SQL query, it's HQL.

If you want to query for only certain fields, you can use a criteria query with a projection.
Example:
def userProperties = User.withCriteria {
projections {
property('id')
property('name')
property('part')
property('description')
}
}
This query will return an array of Strings (or whatever the database column type is mapped to) for each matching row, instead of a domain object.

It will return an ArrayList of objects you only have to access that objects values. For example:
def result = Code.findAll("from Code as c where c.user_code=?",[pass])
result[0].user_code
Where my Code class is something like this:
class Code {
String user_code
boolean flg_active
static constraints = {
user_code nullable:true, blank:true, size:0..Text.MID
flg_active nullable:true, blank:true, default:1
}
}

Related

How to bulid a criteria query to get the data of my domain

I know that have to be really easy, but I'm new in grails and I don't find any clear answer. That I want to do is read and get with a criteria query the data that I have in my domain do a search for each parameter.
This is my domain Person:
String name
String surname
String address
String village
String country
This is that I'm trying to do:
def getData = Person.createCriteria()
I can see in the log that I have an object (com.mypackagename.Person: 1.), but not the data that I have in the database. example (myname, mysurname, myaddress, myvillage, mycountry)
I only have one row of data in my database and I want to get the data of every column and do a search for each parameter
Thanks in advance.
Let me show you the code first, then I'll explain it:
class SomeController {
def search() {
def people = Person.withCriteria {
params
.findAll { name, value -> name in ['name', 'surname', 'address', 'village', 'country'] }
.each { name, value -> eq(name, value) }
}
// Do as you please with 'people'; a list of Person instances.
}
}
Ok, so let's say you have a controller method (ex. search()) which receives the query parameters from the user. The parameters would be in the params Map. For example, if the user searches for the name John and the country USA, params would look like this: [name: 'John', country: 'USA']. Even though there are other search parameters available, we won't use them because the user did not specify them.
Within the criteria query, first search for the param key/value pairs which you care about; the searchable properties of Person. Then, for each of those pairs call eq(String propertyName, Object value) to set up the query criteria (the WHERE clause).
Using the example data, Hibernate will generate SQL that looks something like this:
SELECT name, surname, address, village, country
FROM person
WHERE name = 'john' AND country = 'USA'
And that's it!
Note: You will see the same output in the log (ex. com.mypackagename.Person: 1). That's because you're logging personInstance.toString(). So if you want the log entry to look differently, you'll need to override Person.toString() A very easy way to remedy this is to use Groovy's #ToString AST.
For more about creating criteria queries, take a look at my series of articles. I cover criteria queries using SQL terminology.
Try to use:
def persons = Person.createCriteria().list{}
or if you want just one result:
def persons = Person.createCriteria().list {
maxResults 1
}
Moreover please read about using Criteria and Querying with GORM

Grails Criteria query with a condition on data

I have a database table storing data for this Grails domain class using vanilla GORM:
class A {
String propOver // may be null
String propBase
}
I want to create a search query that searches against the propOver property if it contains a value, otherwise against the propBase property. Or, to word this differently, propOver overrides propBase when it exists.
I need something that works like this pseudo-code:
def results = A.createCriteria().list{
if propOver isn't null: // the heart of the problem
eq('propOver', search_input)
else
eq('propBase', search_input)
}
Is it even possible?
Please note that one (bad) solution would be to create a 3rd property that stores the propOver ?: propBase value, but it violates the DRY principle, and I'd prefer avoiding modifying the DB.
This will do?
A.createCriteria().list{
or {
eq 'propOver', search_input
and {
isNull 'propOver'
eq 'propBase', search_input
}
}
}

GORM criteria like query on string set

I have a domain as below:
class Event {
String name
Set tags
//.... other properties
static hasMany = [tags: String]
}
Now, I want to implement an query for search for Event using a list of String. The search should support a 'like' based search. i.e if an Event has tag like 'annual meeting', then string 'meeting' should give that event as result.
Can this be achieved using GORM criteria?
Due to https://hibernate.atlassian.net/browse/HHH-869 there is no way to query a collection of value types with Hibernate (which GORM uses)
You must use HQL instead.

findBy multiple attributes (findAllWhere)

I have an object from which I must filter certain attributes, some of which could also be "null". I have a Filter object and a Product object.
In the Filter object I have certain attributes reflecting the Product object which can be filled out or be left blank. Here a shortened view on the classes.
Product: String name, Boolean isEmpty, ...., belongsTo [Producer, Distributor]...
Filter: Boolean isEmpty, ... belongsTo [Producer, Distributor]...
With this filter I can search for all Products having certain attributes (empty, Producer, Distributor).
I have an export functionality where I can select the filter and it outputs the information based on that selection for the Products.
As all of these attributes can be null, but also contain a value, I first of thought to construct an own search query (combining strings etc) to construct an SQL-string and then using Product.findAll(string_query, string_params). But as this is quite tedious, I changed it now to someting like this:
if(filter.producer)
prods = Product.findAllWhere(producer:filter.producer)
if(filter.distributor)
prods = prods.findAll {it.distributor == filter.distributor}
if(filter.isEmpty!=null) //as it could be NULL but also false/true
prods = prods.findAll {it.isEmpty == filter.isEmpty}
But this becomes quite a larger task if I have 10-15 attributes to be filtered. I'm not very experienced with Grails or Groovy but I guess this can be solved easier, right?
I believe you'll find Grails Criteria queries to be a very nice way to accomplish tasks like this. See:
http://grails.org/doc/latest/guide/single.html#criteria
http://viaboxxsystems.de/the-grails-hibernatecriteriabuilder
Your sample might look something like this when expressed as a criteria query:
def prods = Product.createCriteria().list {
if(filter.producer) eq("producer", filter.producer)
if(filter.distributor) eq("distributor", filter.distributor)
if(filter.isEmpty != null) eq("isEmpty", filter.isEmpty)
}

How to retrieve the latest created db entry?

I have the following class and need to manually increment the nextId field.
class SomeIdClass {
Family family
Integer nextId = 0
long timeCreated = new Date().time }
So far I've been trying to retrieve and the latest db entry to increment it and I'm just not having any luck with that. Or am I just going about it in a totally wrong manner?
Thaks
ps: this is what I tried but get a list of Package.SomeId objects
def si = SomeId.executeQuery(" from SomeId where nextId = (select max( nextId ) from SomeId) ")
My two cents for return the last row in Grails:
DomainClass.find("from DomainClass order by id desc")
You can simply get the last saved value this way:
//works only if the primary key 'id' is non-composite
def lastEntry = SomeIdClass.last(sort: 'id')
//alternative method which will work even for composite primary key
def entryList= SomeIdClass.findAll{[sort:'id',order:'asc']}.last()
You can do this:
def maxNextId = DomainClass.executeQuery("select max(nextId) from DomainClass")[0]
Without seeing the whole context, it's hard to tell what you're doing, but as an aside, this looks pretty questionable. This method to assign ids to domain objects is probably the wrong way to go about it. But in any case, what if a new object gets inserted into the database with a greater nextId in between the time you do the query and use the value?
What about replacing
long timeCreated = new Date().time
with
Date dateCreated
which grails automatically populates, to your domain class?
Then you could do something along the lines of
SomeIdClass.listOrderByDateCreated(max: 1, order: "desc")
Also, you do know that by default grails gives every domain object an id that auto-increments right?
Why not using a sequence? You can use a sequence that is global to all your domain classes or you can define a specific sequence for that domain. You can do something like this:
static mapping = {
id generator: 'sequence', params: [sequence: 'some_name_sequence']
}
..and if for some reason you still need to have a nextId, you can create a get method that returns the value of id, something like:
def getNextId() {
return id
}
If you do this then you would need to define nextId as a transient value.
This of course assuming you don't need id and nextId to be different.
From http://www.hsqldb.org/doc/guide/ch09.html#create_table-section
The last inserted value into an identity column for a connection is available using the function IDENTITY(), for example (where Id is the identity column):
INSERT INTO Test (Id, Name) VALUES (NULL,'Test');
CALL IDENTITY();
So, assuming you're using HSQL, you may be able to do:
SomeIdClass.executeQuery("call identity();")
to get the last inserted ID and add to it. MySQL has its own similar feature if HSQL is not the correct route.
This answer is NOT TESTED.
// retrieve the last person
def p = Person.last()
//get the current id
def currentId = p.id
//increment the id manually
def nextId = currentId+1
You can also use the generator in the domain class mappings.
static mapping = {
table 'PERSON'
id generator: 'increment'
version false
}
Ummh, try
SomeIdClass.where {
// any criteria - or none
}.max('nextId').list()[0]
But of course you should be using a sequence generator for ids.

Resources