how to get data from database to controller in grails 3 - grails

i am new in grails 3 and i wanted to know that how we can get the values from the database to the controller
i tried
def std = Students.get(1)
but it returns only the id not the actual value
plzzzz can anyone help me

You could also do:
def std = Students.findById(id);

If you are printing the result of get, the toString() default methods is call if you haven't create your own. Then if you do:
def std = Students.get(1)
println std
Students: 1 will be printed
You can implement your toString() method as:
Students{
String name
String toString(){
name
}
}
In this case the result of println will be its name.
If you want to print all fields of the object just do
println std.dump()

Related

Grails Cannot get property 'id' on null object

I am getting this error: Cannot get property 'id' on null object and i can't understand the problem.
Here is my code in provionController.groovy
CreateCriteria returns one element, I verified in the database, size = 1 but when i tried to display the Id, I get this error.
def prov_model = null
def model = Provision_model.CreateCriteria{
gilt_air{
eq("air",air)
}
gilt_coo{
eq("coo",coo)
}
le("date_from", per.begin)
ge("date_to", per.end)
eq("active", 1)
}
println(model.size())
prov_model = model[0]
println(prov_model.id)
but when I am getting it directly by method get(), it hasn't no problem
prov_model = Provision_model.get(57)
println(prov_model.id)
1st: the method is called createCriteria(), not CreateCriteria()
2nd: the method itself DOES NOT invoke any db operation. You have to call list() or get() etc. on it to get the query results
If order to execute the query and store the results in model, replace this
def model = Provision_model.CreateCriteria
with
def model = Provision_model.withCriteria
#injecteer and #Donal both have very valid input. First, you need to address the syntax issue, here is an example of one way to format your criteria:
def prov_model = null
def model = Provision_model.createCriteria().get() {
gilt_air{
eq("air",air)
}
gilt_coo{
eq("coo",coo)
}
le("date_from", per.begin)
ge("date_to", per.end)
eq("active", 1)
}
Keep in mind that by using .get() you are limiting the return from the criteria to one record. Second, if you try writing the criteria both ways, using withCriteria and using the format above and it still doesn't work, your problem may be in the domain model or the configuration of the database.

how to to find a string in groovy list

question from a groovy newbie:
sql is initiated as follows
final Binding binding = new Binding();
binding.setProperty("sql", sql);
final groovy.sql.Sql sql = Sql.newInstance(dbConfig.getUrl(), dbConfig.getUserName(), dbConfig.getPasswd(),"oracle.jdbc.OracleDriver");
I am running a query in groovy like this
def listOfRows = sql.rows (select column1 from table1);
listOfRows when printed shows contents like [[column1_name:value1], [column1_name:value2], [column1_name:value3]]
I want to check if value2 (a String) exists in the returned list of values from the above query.
I have tried doing listOfRows.contains('value2') and listOfRows.find('value2'),
it complains that the method does not exist for lists..
what's the best way of doing this ?
EDITED: I have corrected the list of printed values. What's being returned is List<GroovyResultSet>
and I have also added the definition of sql.
I would suggest you to take a look at groovy documentation, and particularly to collections documentation (both tutorial and JDK/GDK).
in that case, the most specifically adapted solution would be to use Collection#find() ... with something like
listOfRows.find { it.contains(':value2') }
Which can be translated into human-readable
find the first element in this collection which string contains ":value2".
You probably want
listOfRows.column1.contains( 'value2' )
You are probably invoking this method which takes a GString (note that GString != String) as an argument. According to this question, a string in single quotes is a standard java string, and a string in double quotes is a templatable string.
'hello' //java.lang.String
"hello" //groovy.lang.GString
Try this:
listOfRows.contains("value2")
what i ended up doing is following :
iterate the listOfRows, get all the values for column1 from each GroovyResultSet into a listOfValues ,then check for my values in that list.
def listOfValues=[];
listOfRows.collect(listOfValues){it.getAt('column1')};
if(listOfValues.size()==3){
println('success');
}

Overriding Joda DateTime toString in Groovy

So I'm using the JodaTime plugin in a grails project I'm implementing and I really don't like that it spits out the ISO8601 date format when I do a toString. I've been constantly putting toString and passing in the default.date.format from the messages file, but that's cumbersome. The majority of cases I just want it to do that automatically. So naturally it makes sense to take advantage of Groovy's fabulous metaprogramming to override toString on the DateTime class. But alas it doesn't work. Hence this discussion:
http://jira.codehaus.org/browse/GROOVY-4210
So according to said discussion, if our class implements an interface to implement the toString method we need to override the interface's metaclass. Looking at the joda code base, DateTime implements the ReadableDateTime interface which in turn inherits from ReadableInstant which is where the method signature is defined. The actual implementation is done 4 classes up in the class hierarchy for DateTime (DateTime inherits from BaseDateTime inherits from AbstractDateTime inherits from AbstractInstant which implements toString without parameters). With me so far?
So in theory this means I should override either the ReadableDateTime interface which doesn't actually have the toString signature or the ReadableInstant one which does. The following code to override toString on ReadableDateTime does nothing.
ReadableDateTime.metaClass.toString = { ->
delegate.toString(messageSource.getMessage(
'default.date.format', null, LCH.getLocale()))
}
So then trying with ReadableInstant:
ReadableInstant.metaClass.toString = { ->
delegate.toString(messageSource.getMessage(
'default.date.format', null, LCH.getLocale()))
}
also does not have the desired result for the DateTime.toString method. However, there are some interesting affects here. Take a look at the following code:
def aiToString = AbstractInstant.metaClass.getMetaMethod("toString", [] as Class[])
def adtToString = AbstractDateTime.metaClass.getMetaMethod("toString", [] as Class[])
def bdtToString = BaseDateTime.metaClass.getMetaMethod("toString", [] as Class[])
def dtToString = DateTime.metaClass.getMetaMethod("toString", [] as Class[])
def date = new DateTime()
println "ai: ${aiToString.invoke(date)} "
println "adt: ${adtToString.invoke(date)} "
println "bdt: ${bdtToString.invoke(date)} "
println "dt: ${dtToString.invoke(date)} "
The first 3 methods show my date formatted just how I'd like it. The last one is still showing the ISO8601 formatted date. I thought maybe the JodaTime plugin for grails might be overriding the toString and they do add a few methods to these interfaces but nothing to do with toString. At this point, I'm at a loss. Anyone have ideas?
Thanks
You cann't override DateTime#toString(), becouse DateTime class is final
public final class DateTime
But if you want another date format, you can use toString(org.joda.time.format.DateTimeFormatter)
for example
def date = new DateTime();
date.toString(ISODateTimeFormat.basicDate()); // format yyyyMMdd

Groovy Dynamic List Interaction

I am using an older version of grails (1.1.1) and I am working on a legacy application for a government client.
Here is my question (in psuedo form):
I have a domain that is a Book. It has a sub domain of type Author associated with it (1:many relationship). The Author domain has a firstName and lastName field.
def c = Book.createCriteria()
def booklist = c.listDistinct {
author {
order('lastName', 'asc')
order('firstName', 'asc')
}
}
Let's say I have a list of fields I want to use for an excel export later. This list has both the author domain call and the title of the column I want to use.
Map fields = ['author.lastName' : 'Last Name', 'author.firstName', 'First Name']
How can I dynamically call the following code--
booklist.eachWithIndex(){
key, value ->
println key.fields
}
The intent is that I can create my Map of fields and use a loop to display all data quickly without having to type all of the fields by hand.
Note - The period in the string 'author.lastName' throws an error when trying to output key['author.lastName'] too.
I don't recall the version of Groovy that came with Grails 1.1, but there are a number of language constructs to do things like this. If it's an old version, some things may not be available - so your mileage may vary.
Map keys can be referenced with quotes strings, e.g.
def map = [:]
map."person.name" = "Bob"
The above will have a key of person.name in the map.
Maps can contain anything, including mixed types in Groovy - so you really just need to work around string escapes or other special cases if you are using more complex keys.
You can also use a GString in the above
def map = [:]
def prop = "person.name"
map."${prop}" = "Bob"
You can also get a map of property/value off of a class dynamically by the properties field on it. E.g.:
class Person { String name;String location; }
def bob = new Person(name:'Bob', location:'The City')
def properties = bob.properties
properties.each { println it }

Setting Grails domain id in Bootstrap.groovy

Is it possible to explicitly set the id of a domain object in Grails' Bootstrap.groovy (or anywhere, for that matter)?
I've tried the following:
new Foo(id: 1234, name: "My Foo").save()
and:
def foo = new Foo()
foo.id = 1234
foo.name = "My Foo"
foo.save()
But in both cases, when I print out the results of Foo.list() at runtime, I see that my object has been given an id of 1, or whatever the next id in the sequence is.
Edit:
This is in Grails 1.0.3, and when I'm running my application in 'dev' with the built-in HSQL database.
Edit:
chanwit has provided one good solution below. However, I was actually looking for a way to set the id without changing my domain's id generation method. This is primarily for testing: I'd like to be able to set certain things to known id values either in my test bootstrap or setUp(), but still be able to use auto_increment or a sequence in production.
Yes, with manually GORM mapping:
class Foo {
String name
static mapping = {
id generator:'assigned'
}
}
and your second snippet (not the first one) will do the job (Id won't be assigned when passing it through constructor).
What I ended up using as a workaround was to not try and retrieve objects by their id. So for the example given in the question, I changed my domain object:
class Foo {
short code /* new field */
String name
static constraints = {
code(unique: true)
name()
}
}
I then used an enum to hold all of the possible values for code (which are static), and would retrieve Foo objects by doing a Foo.findByCode() with the appropriate enum value (instead of using Foo.get() with the id like I wanted to do previously).
It's not the most elegant solution, but it worked for me.
As an alternative, assuming that you're importing data or migrating data from an existing app, for test purposes you could use local maps within the Bootstrap file. Think of it like an import.sql with benefits ;-)
Using this approach:
you wouldn't need to change your domain constraints just for
testing,
you'll have a tested migration path from existing data, and
you'll have a good data slice (or full slice) for future integration tests
Cheers!
def init = { servletContext ->
addFoos()
addBars()
}
def foosByImportId = [:]
private addFoos(){
def pattern = ~/.*\{FooID=(.*), FooCode=(.*), FooName=(.*)}/
new File("import/Foos.txt").eachLine {
def matcher = pattern.matcher(it)
if (!matcher.matches()){
return;
}
String fooId = StringUtils.trimToNull(matcher.group(1))
String fooCode = StringUtils.trimToNull(matcher.group(2))
String fooName = StringUtils.trimToNull(matcher.group(3))
def foo = Foo.findByFooName(fooName) ?: new Foo(fooCode:fooCode,fooName:fooName).save(faileOnError:true)
foosByImportId.putAt(Long.valueOf(fooId), foo) // ids could differ
}
}
private addBars(){
...
String fooId = StringUtils.trimToNull(matcher.group(5))
def foo = foosByImportId[Long.valueOf(fooId)]
...
}

Resources