Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
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
- is duplicated by
-
GRAILS-3453
CLONE -*list* and *findAll* methods return duplicate items when using Hibernate-mapped Java classes as the domain model broken in 1.0.3
-
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.