Grails GORM find by value inside map of Domain - grails

I am using Grails 2.2.4 and having one Domain contains value as map and I want to find domain object using key of map. Please help me to resolve this issue.
Student.groovy
package com.grails
import java.util.Map;
class Student {
String firstName
String lastName
Map address
static constraints = {
}
}
When My application are run I can see that Grails application create tables in database are as follow:
1) first table
student
id
version
first_name
last_name
indexes
2) second table
student_address
address
addres_idx
addres_elt
When I save Domain as:
def std = new Student()
std.firstName = 'Piyush'
std.lastName = 'Chaudhari'
std.address = [city:'Surat',state:'Gujarat',pincode:'38001']
std.save(flash:true)
values are insert in database as follow:
student table
ID VERSION FIRST_NAME LAST_NAME
1 0 Piyush Chaudhari
student_address table
ADDRESS ADDRESS_IDX ADDRESS_ELT
1 city Surat
1 state Gujarat
1 pincode 38001
Now, I want data or row using GORM like Student.findBy_____ or Student.findAllBy______
where 'city' = surat
Any one can help me to resolved this issue?

You can use:
Student.findBy<FieldName1>And<FieldName2> (<FieldNameParameter1>, <FieldNameParameter2>)
Or Either:`
Student.list().find { it.address.city == 'Surat' }
Student.list().findAll { it.address.city == 'Surat' }
`

I don't think that you can search things like this using maps.
Maybe you can do this:
def students = Student.list()
def result = students.each { student -> student.address.city == 'Surat' }
println("Resultado" + result)
But this is a very bad way to do this kind of things

Define an address class, and then add an address field to the student class (this will change how your tables are mapped in the database):
class Student {
String firstName
String lastName
Address address
static constraints = {
}
}
class Address {
String city
String state
String pincode
}
Address should be another entity in your domain, not a map of values. Remember that Grails GROM is an ORM, so you should design your domain using a OOP model in order to take advantage of the dynamic finders and criterias for doing queries.
With those changes in place, you can now use a simple criteria:
def students = Student.withCriteria{
'address'{
eq('city', 'surat')
}
}
More information about criterias in the grails docs:
http://grails.org/doc/latest/ref/Domain%20Classes/withCriteria.html
http://grails.org/doc/latest/guide/single.html#criteria
If you want to use Dynamic finders, you will have to get all the address with city = 'surat' and then use a findByAddressInList(...). But i think that in this case, criterias is a better approach

Related

get a specific property for a domain in Grails

i'm making a tables cleaning service that takes the table name and the date field as arguments , here is the service code :
def cleanTables(tableName , dateField) {
def comparisonDate
def numOfRecordsDeleted
use (TimeCategory){
comparisonDate=new Date() -1.year
}
numOfRecordsDeleted=tableName.where { dateField <=comparisonDate }.deleteAll()
log.info("deleted : " +numOfRecordsDeleted)
}
i'm successfully passing to this service the table name but i can't pass the date field , so how to get a specific property from a domain for example a domain named Payments got a property dateCreated , so i pass to my service Payments and dateCreated.
With where queries you have access to criteria query methods such as eq(), or in this case, le(). Those methods take the name of the property as an argument, which is what you need. I tweaked the code a bit because you're actually interacting with domain classes, not tables. Small distinction, until you start working with HQL.
def cleanDomainClass(String domainClassName, String dateField) {
def domainClass = Class.forName("some.package.$domainClassName")
def comparisonDate = use (TimeCategory) { new Date() -1.year }
def numOfRecordsDeleted = domainClass.where { le(dateField, comparisonDate) }.deleteAll()
log.info("deleted : $numOfRecordsDeleted")
}

Grails 1:m get most relations

I'm relatively new to Grails.
I have the following
class House {
Integer number
Integer maxResidents
static belongsTo = [town: Town]
}
class Town {
String name
static hasMany = [houses: House]
}
I want to get five towns with most Houses. I have seen the possibility to create a criteria but I can't deal with it now. Can someone support?
Thank you!
As you have a bidirectional association you can do this with a query on House:
def result = House.withCriteria {
projections {
groupProperty("town", "town")
rowCount("numHouses")
}
order("numHouses", "desc")
maxResults(5)
}
This would return you a list of results where each result res has the town as res[0] and the number of houses as res[1]. If you'd prefer each result to be a map giving access to res.town and res.numHouses then you should add
resultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
after the maxResults line (along with the appropriate import at the top of your file).

Sort based on column in child table using GORM?

I have a table called employee and child table address.
Now I want to get a list of employees sort by address1 in address table using GORM.
Employee.findAllByName(name, [max: maxRecords, offset: 100,sort: Address.address1, order: desc])
the above statement is not working, any suggestions would be appreciated.
Thanks
Try using a criteria query like so...
def c = Employee.createCriteria()
def results = c.list (max: maxRecords, offset: 100) {
eq("name", name)
address {
order("addres1", "desc")
}
}
This works for me!
Another option is to add a default sort order like so...
class Address{
…
static mapping = {
sort address1:"desc"
}
}
However, I always prefer to do things as an 'as-needed' basis rather than define that sorting be done every time even when it may not be needed. U pick. Enjoy!

GORM, giving names for the columns of a joinTable with a composite id

Working with Grails 1.3.7, I've to deal with a legacy DB. I've a domain object ''Cake'' which have it's own collection of embedded ''Ingredients'', in a join table.
Ingredient.groovy
class Ingredient {
String name
IngredientCategory category
mapping {
table "foo_ingredient"
version false
id composite:['name', 'category']
columns {
word column:"the_name"
category column:"lol_category_id"
}
}
}
Cake.groovy
class Cake {
String name
static hasMany = [ ingredients : Ingredient ]
static mapping = {
table "foo_cake"
version false
columns {
id column:"id"
name column:"the_name"
}
ingredients joinTable: [
name : "foo_cake_ingredient",
key : "cake_id"
]
}
}
Problem is, Grails expect that the table ''foo_cake_ingredient'' to have two columns ''ingredient_name'' and ''ingredient_category_id''. I would like to specify manually those column names and not let Grails (wrongly) guess those. I can't figure how to do that.
I showed how to do this here: http://grails.1312388.n4.nabble.com/Composite-foreign-key-td3046351.html#a3046436
You probably have to create a hibernate xml mapping for the two tables in this relationship.
Have you read http://jasonrudolph.com/blog/2006/06/20/hoisting-grails-to-your-legacy-db/ ?

Grails GORM Domain class relationship

Grails 1.1.1
Goovy 1.5.7
In a relationship such this:
Author 1 -- n Book n -- 1 Publisher
Defined in Grails:
class Author {
String firstName
String lastName
static hasMany = [books: Book]
static constraints = {
books(nullable: true)
}
}
class Book {
String title
Author author
Publisher publisher
static constraints = {
author(nullable: true)
publisher(nullable: true)
}
}
class Publisher {
String name
static hasMany = [books: Book]
static constraints = {
books(nullable: true)
}
}
I want to load a Book with the values of Publisher and Author.
When i get a Book with the query:
def book2 = Book.findAllByAuthor(author)
I get the response with the autor assosiated but the publisher only have the id and name class in the other query:
def book3 = Book.findAllByPublisher(publisher)
I retrieve me the inverse result,i have the book with the publisher data but the author only have the id and the class name.
Where is the error in the defined model ? o there is an error in the way to do the queries ?
Edit:
I need the way to retrieve the values only with the query like this:
def book2 = Book.findAllByAuthor(author, [fetch:[publisher:'eager']])
In this one I can manage the value of publisher.
Question: If publisher had a hasmany or Domain related, getting the book I'm able to read the attributes?
Thanks.
Thanks.
Lazy fetching is used by default with gorm associations. If you want to enable eager fetching, you can modify the ORM DSL by adding the following mappings block to your Author domain class:
static mapping = {
books lazy:false
}
or you could change the fetch mode in the domain object by adding following code after your books relationship is defined.
static fetchMode = [books:"eager"]
Doing the same to your Publisher domain object should allow you to accomplish what you want. You do want to be careful of the consequence that you may load more data than you intend to.
Shouldn't the get() method return what you are looking for?
Example: def book2 = Book.get(author)
You'd better use Criteria and explicitly define which relations should be loaded eagerly. Just mention relation in the query.
Example:
def c = Teacher.createCriteria()
List<Teacher> results = c.list {
subjects {
attendees {}
}
}

Resources