grails PreUpdateEventListener infinite loop - grails

I have PreUpdateEventListener in my application. It looks like:
public boolean onPreUpdate(PreUpdateEvent event) {
if (!needClasses.contains(entity?.class?.name))
return false
def entity = event.entity
boolean rez = false
entity.withSession {org.hibernate.Session session ->
def tryFind = Book.executeQuery("select s.id from ${entity.class.name} s where s.id=? ".toString(), [entity.id])
rez = (tryFind != null && tryFind.size() > 0)
}
return !rez
}
while executing Book.executeQuery it call onPreUpdate again, goes to this line and so on. finally it crash with stack overflow exception by this infinite self calling.
can anybody help me?

Is it possible that the entity is different then an instance of Book ?
Try using findAll() method instead of executeQuery.
Book.findAll("From ${entity.class.name} s where s.id=? ", [entity.id])
//OR this is same as above
def exist = entity.class.get(entity.id)
If the entity can be of different type then Book, instead of calling findAll on the Book class you should call it on proper class.
First try using findAll, I guess it would fix your issue.

Related

GORM Where query composition on return value

I noticed some behaviour I don't quite understand. It's possible to chain where queries as long as the preceding where query wasn't returned from a function.
def w = Subscription.where { topicId == 1 }
w.where { user.id == 1 }.findAll()
//works as expected
def f() {
Subscription.where { topicId == 1 }
}
f().where { user.id == 1 }.findAll()
//doesn't filter by user.id
def f() {
Subscription.where { topicId == 1 }
}
f().build { eq 'user.id', 1L }
//works
I don't mind using DetachedCriteria#build(). I'd just like to understand :-D
--- Edit
Grails 2.4.2
Grails contains a global AST transformation...
that transforms where methods into detached criteria queries.
It essentially looks for uses of where() and changes the code so that it uses detached criterias. Most likely, calling where() as you are, on the return of a method, particularly a method which returns Object, is not being acknowledged up by the AST, so the query basically ends up being unchanged and doing nothing.
It's nothing that Groovy is doing, but rather something Grails-specific. I do not claim a full, nor anything near full, understanding of what's happening, but you can get the gist of it by looking at the DetachedCriteriaTransformer source code.

GORM querying: findAllByPropertyNotInList or findByPropertyNotInList do not exist, any equivalency?

The next code works:
self query1 = DomainClassExample.findAllByPropertyInList("hi","bye")
But if I add Not, the dynamic finder does not exist (it DOES exists: check the answer):
self query2 = DomainClassExample.findAllByPropertyNotInList("hi","bye")
I want to get all the DomainClassExample which don't have the property "hi" or "bye". Is there any dynamic finder for that purpose? Should I use the Where Query. How?
First, a minor correction. It's not a method expression. It's a dynamic finder. Now, as to your actual problem, you'll need to use the criteria API for this...
def c = DomainClassExample.createCriteria()
def matchingProperties = c.list {
property {
not { 'in'(["hi","bye"]) }
}
}
You might run into an issue with the word 'property' and I haven't actually tested the code I just wrote. But that is the gist of it.
In Grails 1.3.9, given the following domain:
class User {
String username
....
}
this works in our application without any issues:
def userList = User.findAllByUsernameNotInList(["user1#testdomain.com","user2#anotherdomain.com"])

different types of null in groovy

I have a method that looks like this:
static UserEvent get(long userId, long eventId) {
UserEvent.find 'from UserEvent where user.id=:userId and event.id=:eventId',
[userId: userId, eventId: eventId]
}
I'm calling it two times with some test data:
println UserEvent.get(1, 1) //I know this has value
println UserEvent.get(1,2) //I know this does not
The above two statements result in:
scheduler.UserEvent : null
null
Question
What is the difference? How can I write an If condition for when something is present or not..
Update
I'm creating the object like this:
def event = Events.findById(params.eventid)
def user = User.findById(params.userid)
UserEvent.create(user, event, true)
#tim_yates is right, the object that is retrieved doesn't have an id property. Looks like an M to M relationship.
So in the first case an instance is being returned but it's ID is null.
In the second case the object isn't found.
You can use something like:
def ue = UserEvent.get(userId, eventId)
if (ue && ue instanceof UserEvent) { //do something }
else { //do something else }
Hope this helps.
The first case returns an instance of UserEvent, which inside of an if statement, should return true. The second case returns null, which inside of an if statement, should return false.

Grails GSP render problem

I've got a domain class which I want to, at run time, do a database call to populate a list of objects as a property. I have a tree with a 'headMember' property and that property is an object which has the following function:
def marriages = {
def marriages = Marriage.findAll("from Marriage as m where m.mainMember.name=:name", [name:name])
return [marriages:marriages]
}
in my GSP, I use ${tree?.headMember?.marriages} to access the 'headMember' property of the model which is passed to the view 'tree' from the following function in the relevant controller:
def show = {
def tree = Tree.get(params.id)
render(view:'show', model:[tree:tree])
}
when I view this in my browser, i get:
Member$_closure1#3708ab98
where I'd expect a list.
Any ideas what I'm doing wrong?
Cheers.
When you call marriages, you are calling a closure and this closure is returned. I think that you should rework it to be a method, something like that:
static transients = ['marriages'] // tell hibernate that marriages is not a persistent property
List<Marriages> getMarriages(){
return Marriage.findAll("from Marriage as m where m.mainMember.name=:name", [name:name])
}
This way, when you call ${tree?.headMember?.marriages} in your GSP, the getMarriages() method is called and list of marriages should be returned.

Is there a 'not in' equivalent in GORM?

Is this possible to convert in createCriteria()?
SELECT * FROM node WHERE (node.type = 'act' AND nid NOT IN (SELECT nid FROM snbr_act_community)) LIMIT 10
I know there's a 'in' operator and here's what I have so far:
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
eq('type', 'act')
}
maxResults(10)
}
Just want to see if this is possible. Otherwise, I guess this is possible in HQL right?
thanks Sammyrulez for the code. got an idea from that. tested it but it didn't work. i fixed it and here's the final working code:
def ids = [14400 as long, 14401 as long]
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
eq('type', 'act')
not { 'in'(ids) }
}
maxResults(10)
}
now i know how to use 'not' operator. thanks a lot!
not tried it myself but looking at the Grails doc and hibernate api you create nodes on this builder map with the static methods found in the Restrictions class of the Hibernate Criteria API 1. So something like
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
not(in('propertyName', ['val1','val2']))
}
maxResults(10)
}
Since you chain the in method (that returns a Criterion) with the not method (that takes a Criterion as argument and returns a negated version)
this is the solution :
def resultat=EnteteImputationBudgetaire.createCriteria().get{
between("dateDebutPeriode", dateDebut, dateFin)
and{ eq 'natureImputationBudgetaire','FONCTIONNEMENT' }
maxResults(1)
}
def resultat2=ParametragePlanBudgetaire.createCriteria().list() {
like('composantBudgetaire','6%')
if(resultat?.details) {
not {
'in'('composantBudgetaire',resultat?.details?.imputationBudgetaire)
}
}
}
According to Grails documentation about creating criteria here, you can use something like this:
not {'in'("age",[18..65])}
In this example, you have a property named "age" and you want to get rows that are NOT between 18 and 65. Of course, the [18..65] part can be substituted with any list of values or range you need.
Just remembering: in this case you don't have to use parenthesis and you can use inList, for example:
not { inList 'age',[18..65] }

Resources