1

I've got a domain called Planning that has a hasMany of another domain called Employee included in it. I'm trying to do a findAll of these plannings where the plannings contain a particular employee and I can't get it to work.

I'm trying to do it like so, my print statements do print the contains as true

plannings = plannings.findAll{planning->
  if(employee) {
    log.info("find plannings with employee ${employee} ${planning.employees.contains(employee)}")
    planning.employees.contains(employee)
  }
}

I'm not doing this as a Hibernate query as this broke the application in another weird way. This code is executed in a for each and for whatever reason that causes some weird behavior with Hibernate.

doelleri
  • 19,232
  • 5
  • 61
  • 65
Rodin10
  • 327
  • 3
  • 15

2 Answers2

1

The closure must return a boolean value - see http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Collection.html#findAll(groovy.lang.Closure)

This should work (not tested):

 plannings = plannings.findAll{planning-> planning.employees?.contains(employee)}              

BTW: I wouldn't assign the filtered list to the origin plannings list. Extract a a new expressive variable like planingsOfEmployee or something similar.

Peter
  • 4,752
  • 2
  • 20
  • 32
  • 3
    `findAll` does not have to return a `boolean`, whatever it returns will be converted to a boolean using Groovy's truthiness rules https://mrhaki.blogspot.com/2009/08/groovy-goodness-tell-groovy-truth.html – Dónal May 14 '19 at 09:33
  • That still returns an empty list – Rodin10 May 14 '19 at 09:41
  • 1
    @Rodin10: `contains` will use `equals` method of the `Employee` class (I guessed the class name), in case `equals` is not overwritten, object identity will be used. Are you sure, that your `employee` will match? @Dónal: Good point! Thanks for pointing out my sloppy formulation. – Peter May 14 '19 at 11:33
  • My log.info line says so, I'll try comparing id's thanks for the suggestion. – Rodin10 May 14 '19 at 11:36
  • 1
    @Rodin10: Make sure not to change the Id while the `employee` is in a Set - just mentioned it - see https://stackoverflow.com/questions/5847272/equals-and-hashcode-when-storing-in-a-set-in-hibernate – Peter May 14 '19 at 11:41
  • I've changed it into `if(employee){ planning.employees*.id.contains(employee.id) }` but that didn't change anything. – Rodin10 May 14 '19 at 11:46
  • 1
    I cannot help anymore, you have to provide more code. I suggest, that you write propper unit tests. Create `employees`, `plannings` and use the debugger to check the object. – Peter May 14 '19 at 11:54
1

Without more relevant details around your problem (what's the weird behavior? log traces? hibernate mappings?, etc.) all we can do is to speculate; and if I have to do so, I would say that most likely:

  1. The employee object you are using for comparison is a detached one.
  2. The employee object does not override meaningfully equals and hashCode
  3. You use using this detached employee to do comparisons against against persisted employees (using planning.employees.contains(employee)) found inside planning

Under these circumstances the comparisons will never be true even when they may represent the same objects. If this is your case, you must either:

  1. Use a persisted employee object to do the comparisons.
  2. Or, implement equals and hashCode semantically meaningful for Employee

Hope this helps.

Marco R.
  • 2,667
  • 15
  • 33