Nico Huysamen
Nico Huysamen

Reputation: 10427

Grails Domain Object hasMany irregular behaviour using contains

I'm having an issue where calling .contains() on one of my domain classes' hasMany relationships is not doing the same when running normally, or when debugging. The situation is as follows:

I have 2 domain objects, A and B. A has a hasMany relationship with B.

class A {
    ...
    static hasMany = [bees: B]
    ...
}

Now, during the execution of one of my filters, I grab my current user from the spring security service. This user also contains a single instance of B. What my filter should do is to check if the instance of B in the user is contained in some instance of A.

Assume that the instances of B are actually referring to the same object (since they are).

Now, the issue arises. Calling:

if (instanceOfA.bees.contains(user.instanceOfB)) {
    println 'success'
} else {
    println 'failure'
}

prints failure during normal (or debugging without stepping through the code) execution. However, if I put a break-point there, and step through the code, it correctly executes the contains() and prints success.

I have also implemented equals, hashCode and compareTo in an attempt to resolve this, but with the same behaviour.

Upvotes: 1

Views: 458

Answers (4)

Nico Huysamen
Nico Huysamen

Reputation: 10427

So it seems that using one of the Groovy transform annotations seems to do the trick. Simply adding:

// uid is a uniqe UUID we use to identify with other systems.
@EqualsAndHashCode(includes = ["id", "uid"])

does the trick. Seems a bit strange that the IDE generated methods (using the same fields) did not...

Upvotes: 1

Chris
Chris

Reputation: 8099

This is usually due to lazyloading or cache. Use instanceOfA.bees.id.contains(user.instanceOfB.id) and it always works.

Upvotes: 3

James Kleeh
James Kleeh

Reputation: 12238

I would do this with HQL:

A.executeQuery("select a from A a join a.bees as b where b = :b and a = :a", [a: instanceOfA, b: user.instanceOfB])

Upvotes: 1

micha
micha

Reputation: 49612

Maybe your user.instanceOfB object is a hibernate proxy object and therefore not a real B. You can check this using a debugger or printing user.instanceOfB.getClass().

You can use GrailsHibernateUtil.unwrapIfProxy(proxyObject) to get the real object from the proxy.

Upvotes: 2

Related Questions