grails findAll() method - grails

I am using the findAll() SQL-like method:
MyDomainClass.findAll("firstname='George' and lastname='kuo' and username='kjlop'"),
but I have got problem:
when value starts with number(for example,when age='2poj') it throws an exception
I use grails 1.3.2 and gorm-hbase 0.2.4 plugin and in my domain classes fields have String type.
Here is the Stack Trace:
expecting token in range: '0'..'9', found 'p'
at org.grails.hbase.ghql.LexerRules.nextToken(LexerRules.java:125)
at org.grails.hbase.finders.QueryStringTokenizer.tokenize(QueryStringTokenizer.groovy:59)
at org.grails.hbase.finders.TokenizerStrategy$tokenize.call(Unknown Source)
//---------
I wonder is there any way in groovy change findAll() method work ?
If anybody know solution please help.
Thanks in advance.

You should be able to run a dynamic finder method on the domain object to achieve what you need.
Example:
MyDomainClass.findAllByFirstnameAndAge('Dan', 25)
This works for all data types and enums.

You can try like the Grails example:
MyDomainClass.findAll("from DomainTable as b where b.firstname=:firstname and b.age=:age", [firstname:'Dan Brown', age: 25]
Notice: I don't know if you mistype it, but '25' is a string, so that it can't be age='25'
EDIT:
I don't know how this doesn't work, but in case you want to find with multiple properties, you should use createCriteria().
def c = MyDomainClass.createCriteria()
def results = c.list {
like("firstName", "George%")
like("age", "25");
}
EDIT2: Sorry, createCriteria is not supported by hbase plugin. Based on your condition, I think it's suitable to try DynamicFinderFilter (with approriate import).
// all books written by Dan Brown or J K Rowling
DynamicFinderFilter filterList = new FinderFilterList(Operator.OR)
DynamicFinderFilter filter1 = new Filter('author', 'Dan Brown')
filterList.addFilter(filter1)
DynamicFinderFilter filter2 = new Filter('author', 'J K Rowling')
filterList.addFilter(filter12)
results = Book.findAll(filterList)
The complete example can be find in the plugin page.

Related

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');
}

Grails: Understanding groovy DomainClass.properties

I'm having a hard time finding information about grails functionality:
DomainClass.properties = params
In my particular case, I have these classes:
class parameterType = {
String name
String desc
static hasMany = [codes : parameterCode]
...
}
class parameterCode = {
String code
String desc
static belongsTo = [parameterType : parameterType]
}
My parameterType/edit.gsp has name, desc and an html table with its list of parameterCodes
At first, I had some variation of the scaffolded controller on the 'update' action. That (I know its wrong but it was a beginners code) it first deleted all the parameterCodes and then reassociated them (or recreated them).
With Ajax I was sending the data in this format:
id=1234&name=paramName&desc=paramDesc&codes[0].code=code1&codes[0].desc=codeDesc1&codes[1].code=code2&codes[1].desc=codeDesc2
And in the controller I had this:
def parameterTypeInstance = ParameterType.get(params.id)
def toDelete = parameterTypeInstance.parameterCodes
parameterTypeInstance.parameterCodes = []
toDelete.each{it.delete(flush: true)}
//And this "magic" line reassociated all the properties in parameterType And Created his parameterCodes in the data base:
parameterTypeInstance.properties = params
I honestly don't how it works, and I just wanted to know if there's a way of doing the same thing without having to previously delete the associated parameterCodes.
Cheers
**Update:**
I just found what I was looking for in these links:
http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/
http://omarello.com/2010/08/grails-one-to-many-dynamic-forms/
But I had another error.
These talks about LazyList and decorate(), so I just added the next lines to my ParameterType Class:
def List getExpandableCodeList() {
return LazyList.decorate(codes,FactoryUtils.instantiateFactory(ParameterCode.class))
}
But when I do this in my controller update:
parameterTypeInstance.properties = params
I'm getting this error:
groovy.lang.MissingMethodException: No signature of method: static org.apache.commons.collections.list.LazyList.decorate() is applicable for argument types: (org.hibernate.collection.PersistentSet, org.apache.commons.collections.functors.InstantiateFactory) values: [[cE - EE, cA - AA, cC - CC, cD - DD], org.apache.commons.collections.functors.InstantiateFactory#dd768d]
The data is being recieved in the controller this way:
expandableCodeList[0].desc: AA
expandableCodeList[3].code: cE
expandableCodeList[3].id: 35073
expandableCodeList[1].id: 35076
expandableCodeList[0].code: cA
expandableCodeList[2].code: cD
expandableCodeList[1].desc: CC
expandableCodeList[0].id: 35080
expandableCodeList[3].desc: EE
expandableCodeList[2].id: 35075
Any hints on what I'm doing wrong? should I be sending the data in another format?
Any help would be much appreciated. Thanks.
If I not in error .properties is a method added by groovy to the java.lang.Object , look to this javaodc
There is many way to do what you want to do. Please look to grails documentation on data binding .
For example you can do
bindData(parameterTypeInstance, params, [exclude: parameterTypeInstance.parameterCodes])
look here for more info on bindData
Ok, I'm settings this as an answer:
http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/
At last, lazylist and the decorate() method was what I was looking for. Sadly it takes to take the child collection as a list and it carries out a lot of other issues for me. But its a good solution if anyone needs to make a view with the parent and its child objects the "simple" way.

Strange behavior of gorm finder

In a controller I have this finder
User.findByEmail('test#test.com')
And works.
Works even if I write
User.findByEmail(null)
But if i write
User.findByEmail(session.email)
and session.email is not defined (ergo is null) it throw exception
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
Is this behavior right?
If i evaluate "session.email" it give me null so I think it must work as it do when I write
User.findByEmail(null)
Even more strange....
If I run this code in groovy console:
import myapp.User
User.findByEmail(null)
It return a user that has null email but if I run the same code a second time it return
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
You can't use standard findBySomething dynamic finders to search for null values, you need to use the findBySomethingIsNull version instead. Try
def user = (session.email ? User.findByEmail(session.email)
: User.findByEmailIsNull())
Note that even if User.findByEmail(null) worked correctly every time, it would not necessarily give you the correct results on all databases as a findBySomething(null) would translate to
WHERE something = null
in the underlying SQL query, and according to the SQL spec null is not equal to anything else (not even to null). You have to use something is null in SQL to match null values, which is what findBySomethingIsNull() translates to.
You could write a static utility method in the User class to gather this check into one place
public static User byOptEmail(val) {
if(val == null) {
return User.findByEmailIsNull()
}
User.findByEmail(val)
}
and then use User.byOptEmail(session.email) in your controllers.
Jeff Brown from grails nabble forum has identified my problem. It's a GORM bug. see jira
More info on this thread
This jira too
I tried with debugger and it looks it should be working, as you write. Maybe the groovy itself is a little bit confused here, try to help it this way:
User.findByEmail( session['email'] )

getArtefact return NULL for the "Domain"

I am new to Grails and was trying to follow with the examples in "Beginning Groovy and Grails"
When I was trying out the examples, I had the following issue:
domainClass = grailsApplication.getArtefact("Domain", domainClassName)
The domainClass was returning NULL. But when I use the following snippet, I get the correct Class.
if (!domainClass) {
def artefacts = grailsApplication.getArtefacts("Domain")
domainClass = artefacts.find {item ->
item.name == domainClassName
}
}
What is wrong with the first part? Is there anything else that I need to take care of. I downloaded the example code of the book and I haven't seen any other specific changes.
Thanks in Advance!!
Use the full path of the domain class i.e prefix the package.
The first code snippet works too, the domainClassName just needs to be fully qualified name ie packagename.domainclassname
def domainClassName = 'org.abc.Sample'
def domainClazz = grailsApplication.getArtefact('Domain', domainClassName)

Beginner Groovy

I'm following the code examples in 'The Definitive Guide to Grails' by Graeme Keith Rocher, and have come across a rather unusual stumbling block.
Essentially, 2 domain classes exist - Bookmark & Tag.
Bookmark:
class Bookmark {
static hasMany = [tags:Tag]
URL url
String title
String notes
Date dateCreated = new Date()
}
Tag:
class Tag{
static belongsTo= Bookmark
Bookmark bookmark
String name
}
I'm instructed to launch the Grails Console (is this the same as the groovy console)and create a new object as follows.
def b = new Bookmark(url: new URL('http://grails.org/'), title:'Grails', notes:'Groovy')
This results in:
Result: Bookmark : null
According to the book, GORM automatically provides an implementation of an addTag method. So I code...
b.addTag( new Tag(name: 'grails'))
Only to get whammed with the error message:
Exception thrown: No such property: b for class: ConsoleScript1
groovy.lang.MissingPropertyException: No such property: b for class: ConsoleScript1 at ConsoleScript1.run(ConsoleScript1:2)
The author hasn't accounted for this in the book. I was wondering if anyone could help me out?
Thanks.
Are you reading the 1st edition of the book? If so it's quite outdated. The add* methods have been deprecated since 0.5. It was replaced by addTo* so do this instead:
b.addToTags( new Tag(name: 'grails'))
Assuming your code example shouldn't have Bookmarks defined twice (copy and paste error?) and Tag might look like this:
class Tag {
String name
}
The groovy console is not the same as the grails console. To access the grails console, type grails console in your application directory - you should get a Java GUI app. It's possible that the example will work then because grails add some stuff to the standard Groovy.
Also, your problem isn't the addTag method, but the item b that you defined which cannot be found. Try entering the whole script into the console at once and executing it, instead of executing it line by line.

Resources