Grails
  1. Grails
  2. GRAILS-284

*list* and *findAll* methods return duplicate items when using Hibernate-mapped Java classes as the domain model

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.2.1
    • Fix Version/s: 1.2 final
    • Component/s: Persistence
    • Labels:
      None
    • Environment:
      Mac OS X 10.4.7
    • Testcase included:
      yes

      Description

      The list and findAll methods return duplicate items when using Hibernate-mapped Java classes as the domain model.

      Using Grails 0.2.1.

      This problem can be recreated with the following steps.

      1. Run grails create-app to create a sample app named ejb3_grails_sandbox
      2. Copy the attached Java class into beans into the src/java directory – ejb3_grails_sandbox/src/java/com/jasonrudolph/ejb3example/entity
      3. Edit ApplicationDataSource.groovy and add the bold lines below.

      import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration

      class ApplicationDataSource {
      def configClass = GrailsAnnotationConfiguration.class
      boolean pooling = true
      String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
      String url = "jdbc:hsqldb:mem:testDB"
      String driverClassName = "org.hsqldb.jdbcDriver"
      String username = "sa"
      String password = ""
      }

      4. Add the attached hibernate.cfg.xml file to the hibernate directory

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

      <hibernate-configuration>
      <session-factory>
      <mapping package="com.jasonrudolph.ejb3example.entity" />
      <mapping class="com.jasonrudolph.ejb3example.entity.EmployeeBean" />
      <mapping class="com.jasonrudolph.ejb3example.entity.ComputerBean" />
      </session-factory>
      </hibernate-configuration>

      5. Copy the attached test case into the grails-tests directory.

      import com.jasonrudolph.ejb3example.entity.EmployeeBean;
      import com.jasonrudolph.ejb3example.entity.ComputerBean;

      class EmployeeBeanTests extends GroovyTestCase {

      void testList()

      { // Verify that we're starting with a clean slate assertEquals(0, EmployeeBean.list()?.size()) // Add one employee w/ no computers, and make sure employee count is 1 def janedoe = new EmployeeBean('janedoe', 'Jane', 'Doe', new Date()) janedoe.save() assertEquals(1, EmployeeBean.list()?.size()) // Add a single computer, associate it with the employee, and make sure employee count is still 1 def macbook = new ComputerBean('123', 'Apple', 'macbook') janedoe.computers.add(macbook) macbook.employeeBean = janedoe macbook.save() assertEquals(1, EmployeeBean.list()?.size()) // Add another computer, associate it with the same employee, and make sure employee count is still 1 def iMac = new ComputerBean('456', 'Apple', 'iMac') janedoe.computers.add(iMac) iMac.employeeBean = janedoe iMac.save() assertEquals(1, EmployeeBean.list()?.size()) // Test fails because the list incorrectly contains 2 items }

      }

      6. Run grails test-app

      [java] There was 1 failure:
      [java] 1) testList(EmployeeBeanTests)junit.framework.AssertionFailedError: expected:<1> but was:<2>
      [java] at gjdk.EmployeeBeanTests_GroovyReflector.invoke(Unknown Source)
      [java] at groovy.lang.MetaMethod.invoke(MetaMethod.java:111)
      [java] at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:657)
      [java] at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:350)
      [java] at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:158)
      [java] at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:104)
      [java] at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.java:85)
      [java] at EmployeeBeanTests.testList(EmployeeBeanTests:27)
      [java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      [java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      [java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      [java] at org.codehaus.groovy.grails.support.GrailsTestSuite.runTest(GrailsTestSuite.java:47)
      [java] at grails.util.RunTests.main(RunTests.java:56)

      [java] FAILURES!!!
      [java] Tests run: 1, Failures: 1, Errors: 0

        Issue Links

          Activity

          Hide
          Graeme Rocher added a comment -

          I think the issue here is more to do with the test case. I believe we need to wrap each test case in a transaction otherwise you will get this behaviour because essentially each call to a persistent method in Grails is opening its own unique session.

          This should work fine when called via a controller which uses a single transaction ( and a single session) for the entire scope of the call.

          Show
          Graeme Rocher added a comment - I think the issue here is more to do with the test case. I believe we need to wrap each test case in a transaction otherwise you will get this behaviour because essentially each call to a persistent method in Grails is opening its own unique session. This should work fine when called via a controller which uses a single transaction ( and a single session) for the entire scope of the call.
          Hide
          Graeme Rocher added a comment -

          should be resolved now as we are now binding the hibernate session object for test cases

          Show
          Graeme Rocher added a comment - should be resolved now as we are now binding the hibernate session object for test cases
          Hide
          Matthias added a comment -

          I am experiencing this bug in Grails 1.0.3 with the listOrderBy method.

          I have 10 users in my database, and I return them using "User.listOrderByRegistrationDate(max:10, order: "desc")

          The result should of course be the only 10 users in my DB, but instead it's the newest 7 users, and the 8th newest users is returned 3 times...

          Show
          Matthias added a comment - I am experiencing this bug in Grails 1.0.3 with the listOrderBy method. I have 10 users in my database, and I return them using "User.listOrderByRegistrationDate(max:10, order: "desc") The result should of course be the only 10 users in my DB, but instead it's the newest 7 users, and the 8th newest users is returned 3 times...
          Hide
          Matthias added a comment -

          this won't fix for 1.0.4 anymore? One has to clutter his code with new HashSet(DomainClass.list()) smells in order to circumvent this problem!

          Show
          Matthias added a comment - this won't fix for 1.0.4 anymore? One has to clutter his code with new HashSet(DomainClass.list()) smells in order to circumvent this problem!
          Hide
          Graeme Rocher added a comment -

          Try User.list(sort:"registrationDate", order:"desc") as a workaround. We decided to release 1.0.4 earlier as there was enough demand to do so

          Show
          Graeme Rocher added a comment - Try User.list(sort:"registrationDate", order:"desc") as a workaround. We decided to release 1.0.4 earlier as there was enough demand to do so
          Hide
          Matthias added a comment -

          I see, thanks.

          Show
          Matthias added a comment - I see, thanks.
          Hide
          Peter Ledbrook added a comment -

          Matthias, see GRAILS-5469 which is probably the one you are experiencing.

          Show
          Peter Ledbrook added a comment - Matthias, see GRAILS-5469 which is probably the one you are experiencing.

            People

            • Assignee:
              Peter Ledbrook
              Reporter:
              Jason Rudolph
            • Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development