get a specific property for a domain in Grails - 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")
}

Related

Grails GORM find by value inside map of Domain

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

get the field by field name and set value to it

I wanted to set a value to a field in domain class.
For example,
class Example {
String name
String lastName
}
Now, from response I'm getting domain name, object instance id, field name and value. I have to set the value to the field in domain class.
Here I got the values as
domainName = 'Example'
instanceId = 1
fieldName = 'name'
valueToSet = 'XYZ'
So how should I set value to the field name? May be this is simple but I'm a new with grails and groovy.
Based on the domain name, a new domain instance has to be created at runtime. For this to happen, grailsApplication has to be injected. Here is a sample which can be modeled after in Controller or a Service class:
class SomeService {
def grailsApplication
def someMethod(String domainName, long instanceId,
String fieldName, def valueToSet) {
Class domainClazz = grailsApplication.domainClasses.find {
it.clazz.simpleName == domainName
}.clazz
def domainInstance = domainClazz.get( instanceId )
domainInstance."$fieldName" = valueToSet
domainInstance.save()
}
}
You can populate a Grails domain class by assigning a map to its properties, for example from the params in the controller (using that handy automatic binding). E.g.:
ded example=new Example()
example.properties=params
So you can see from this that the domain object can be treated as a set of properties. Which means you can use strings for keys, so you might have something like:
example['name']='XYZ'
I don't know whether that's what you're asking but I hope it helps.

Sorting Parent and Child in Grails Controller

Hi I'm trying to perform a sort in a controller of parent and child before rendering a json file but I'm not sure how to go about doing it. Here's what I have (excerpt of original code):
class Parent{
static hasMany = [children:Child]
String name
Date dateCreated
}
class Child {
static belongsTo = [parent:Parent]
String name
Date dateCreated
}
In my controller .groovy file I have :
def list(){
def result = Parent.listOrderByDateCreated(order: "desc")
.... more code ....
withFormat{
json {render result as JSON}
xml {render result as XML}
}
}
and the above works (parent is sorted by date created) but I'm not sure how can I sort all the children by date created within the list.
Thank you for your help in advance. Also I'm using Grails 2.3.2
One way is to assume you always want the children sorted by the dateCreated. Add the following to your Parent domain:
static mapping = {
children sort: 'dateCreated'
}
Another way would be to do the sort after you've pulled the results:
def sortedChildren = parent.children.sort { it.dateCreated }
If there is a fancier "grailsier" way to do this via finders or criteria, I do not know.

GORM where query on an embedded object

I have domain classes A and B as follows:
class A {
String prop1
String prop2
B prop3
static embedded = ['prop3']
}
class B {
String prop4
String prop5
}
When I want to query like this:
def q = A.where { prop3.prop4 == 'bla' }
def list = q.list()
I get the following exception:
Cannot get property 'javaClass' on null object. Stacktrace follows:
on the "def q = A.where ..." line.
Any clue what's the problem? I've checked this:
http://grails.1312388.n4.nabble.com/GORM-embedded-object-issue-td1379137.html
but how to "just call them directly" is not quite clear to me. Any other way of querying the embedded objects in GORM?
I finally gave up on the where query and went with the DetachedCriteria approach. Gives me the same flexibility as the where queries, but works with embedded domain objects:
def criteria = new DetachedCriteria(A).build {
eq 'prop1', 'bla2'
}
criteria = criteria.build {
eq 'prop3.prop4', 'bla'
}
def list = criteria.list()
What do you get if you do (assuming B is in src/groovy)
def q = A.where { prop3 == new B(prop4: 'bla') }
def list = q.list()
Embedded components are persisted inside the main domain class (owner) itself. It can be accessed directly using any dynamic finder as you do directly on a domain object.
The above can also be represented in dynamic finders as:
A.findAllByProp3(new B(prop4: 'bla'))

Override Grails dateCreated and lastUpdated for test data only?

I have several Grails 2.1 domain classes that include dateCreated and lastUpdated fields that GORM manages automatically, eg:
class Person {
Date dateCreated
Date lastUpdated
String name
}
I want Grails to automatically fill in these fields at runtime, but I also want to create some test data where I can manually define the values of these dates. The trouble is that Grails automatically sets the values if these fields with an interceptor even when I have specifically set them.
I have seen this SO question which describes how to allow changes to dateCreated, but I need to change lastUpdated as well. Is this possible?
Whoops, my mistake, the approach in the other question does work, but the entity in question was separately being saved somewhere else. It also seems that you need an explicit flush to make things work:
def withAutoTimestampSuppression(entity, closure) {
toggleAutoTimestamp(entity, false)
def result = closure()
toggleAutoTimestamp(entity, true)
result
}
def toggleAutoTimestamp(target, enabled) {
def applicationContext = (ServletContextHolder.getServletContext()
.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT))
def closureInterceptor = applicationContext.getBean("eventTriggeringInterceptor")
def datastore = closureInterceptor.datastores.values().iterator().next()
def interceptor = datastore.getEventTriggeringInterceptor()
def listener = interceptor.findEventListener(target)
listener.shouldTimestamp = enabled
null
}
def createTestPerson() {
def luke = new Person(name: "Luke Skywalker")
withAutoTimestampSuppression(luke) {
def lastWeek = new Date().minus(7)
luke.dateCreated = lastWeek
luke.lastUpdated = lastWeek
luke.save(failOnError: true, flush: true)
}
}
If it is an integration test you can use an hql update statement to manually set lastUpdated.

Resources