]
Strong Liu edited comment on HHH-1283 at 3/30/11 5:18 AM:
----------------------------------------------------------
Unfortunately, this patch will not work reliably unless the data is ordered by parent.
For the HQL in the test case, "select p from Parent p join fetch p.children c",
Hibernate generates:
select
parent0_.name as name4_0_,
children1_.name as name5_1_,
children1_.parent_id as parent2_4_0__,
children1_.name as name0__
from
Parents parent0_
inner join
chlidren children1_
on parent0_.name=children1_.parent_id
Notice that there is no ORDER BY clause.
Unless the DB returns sorted data (e.g., due to an index or primary key), the resultset
probably won't have rows for a each parent in a contiguous block.
The scrolling logic reads sequentially; when it reaches a new parent, it assumes it is
finished with all rows for the current parent. If there are actually more rows for the
current parent later in the resultset then that parent will be returned with fewer
elements than it should contain. Later, when more rows for that parent are found,
Hibernate will (again) return that same parent with the same incomplete set.
The testScroll() test case passes using the patch because the DB happens to return it in
the right order.
It fails as described above using H2, if the data generation method is changed to:
{code}
private void insertTestData() {
Session s = openSession();
Transaction t = s.beginTransaction();
Child child_1_1 = new Child( "achild1-1");
Child child_1_2 = new Child( "ychild1-2");
Child child_1_3 = new Child( "dchild1-3");
Child child_2_1 = new Child( "bchild2-1");
Child child_2_2 = new Child( "cchild2-2");
Child child_2_3 = new Child( "zchild2-3");
s.save( child_1_1 );
s.save( child_2_1 );
s.save( child_1_2 );
s.save( child_2_2 );
s.save( child_1_3 );
s.save( child_2_3 );
s.flush();
Parent p1 = new Parent( "parent1" );
p1.addChild( child_1_1 );
p1.addChild( child_1_2 );
p1.addChild( child_1_3 );
s.save( p1 );
Parent p2 = new Parent( "parent2" );
p2.addChild( child_2_1 );
p2.addChild( child_2_2 );
p2.addChild( child_2_3 );
s.save( p2 );
t.commit();
s.close();
}
{code}
was (Author: stliu):
Unfortunately, this patch will not work reliably unless the data is ordered by
parent.
For the HQL in the test case, "select p from Parent p join fetch p.children c",
Hibernate generates:
select
parent0_.name as name4_0_,
children1_.name as name5_1_,
children1_.parent_id as parent2_4_0__,
children1_.name as name0__
from
Parents parent0_
inner join
chlidren children1_
on parent0_.name=children1_.parent_id
Notice that there is no ORDER BY clause.
Unless the DB returns sorted data (e.g., due to an index or primary key), the resultset
probably won't have rows for a each parent in a contiguous block.
The scrolling logic reads sequentially; when it reaches a new parent, it assumes it is
finished with all rows for the current parent. If there are actually more rows for the
current parent later in the resultset then that parent will be returned with fewer
elements than it should contain. Later, when more rows for that parent are found,
Hibernate will (again) return that same parent with the same incomplete set.
The testScroll() test case passes using the patch because the DB happens to return it in
the right order.
It fails as described above using H2, if the data generation method is changed to:
private void insertTestData() {
Session s = openSession();
Transaction t = s.beginTransaction();
Child child_1_1 = new Child( "achild1-1");
Child child_1_2 = new Child( "ychild1-2");
Child child_1_3 = new Child( "dchild1-3");
Child child_2_1 = new Child( "bchild2-1");
Child child_2_2 = new Child( "cchild2-2");
Child child_2_3 = new Child( "zchild2-3");
s.save( child_1_1 );
s.save( child_2_1 );
s.save( child_1_2 );
s.save( child_2_2 );
s.save( child_1_3 );
s.save( child_2_3 );
s.flush();
Parent p1 = new Parent( "parent1" );
p1.addChild( child_1_1 );
p1.addChild( child_1_2 );
p1.addChild( child_1_3 );
s.save( p1 );
Parent p2 = new Parent( "parent2" );
p2.addChild( child_2_1 );
p2.addChild( child_2_2 );
p2.addChild( child_2_3 );
s.save( p2 );
t.commit();
s.close();
}
ScrollableResults JoinFetch don't set child collection
correctly after the second parent object
-----------------------------------------------------------------------------------------------
Key: HHH-1283
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1283
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.1
Environment: Hibernate 3.1
Oracle10gR2
Oracle JDBC Driver 10.2.0.1.0
Sun JDK 1.5.0_06
Spring 1.2.6
Reporter: Masahiro Hirashima
Attachments: fetch-scroll-collection-3.5.4.patch,
ScrollableCollectionFetchingTest.java, ScrollableResults.zip
ScrollableResults JoinFetch set child collection correctly at first parent object.
but after the second parent object, It set only the first element of a child
collection.
I made the following tables.
CREATE TABLE owners (
id NUMBER(36, 0) NOT NULL PRIMARY KEY,
first_name VARCHAR(30),
last_name VARCHAR(30),
address VARCHAR(255),
city VARCHAR(80),
telephone VARCHAR(20),
version NUMBER(36, 0) DEFAULT 0
);
CREATE TABLE types (
id NUMBER(36, 0) NOT NULL PRIMARY KEY,
name VARCHAR(80),
version NUMBER(36, 0) DEFAULT 0
);
CREATE TABLE pets (
id NUMBER(36, 0) NOT NULL PRIMARY KEY,
name VARCHAR(30),
birth_date DATE,
type_id NUMBER(36, 0),
owner_id NUMBER(36, 0),
version NUMBER(36, 0) DEFAULT 0
);
and inserted the following data.
INSERT INTO owners VALUES (1, 'Betty', 'Davis', '638 Cardinal
Ave.', 'Sun Prairie', '6085551749', 0);
INSERT INTO owners VALUES (2, 'Eduardo', 'Rodriquez', '2693 Commerce
St.', 'McFarland', '6085558763', 0);
INSERT INTO pets VALUES (1, 'Leo', '2000-09-07', 1, 1, 0);
INSERT INTO pets VALUES (2, 'Basil', '2002-08-06', 2, 1, 0);
INSERT INTO pets VALUES (3, 'Rosy', '2001-04-17', 3, 2, 0);
INSERT INTO pets VALUES (4, 'Jewel', '2000-03-07', 4, 2, 0);
INSERT INTO pets VALUES (5, 'Iggy', '2000-11-30', 5, 2, 0);
INSERT INTO types VALUES (1, 'cat', 0);
INSERT INTO types VALUES (2, 'dog', 0);
INSERT INTO types VALUES (3, 'lizard', 0);
INSERT INTO types VALUES (4, 'snake', 0);
INSERT INTO types VALUES (5, 'bird', 0);
and I execute following code.
String hqlJoinFetchTest =
"from Owner owner " +
"left outer join fetch owner.pets as pets " +
"left outer join fetch pets.type " +
"order by owner.firstName, owner.lastName";
Query query = session.createQuery(hqlJoinFetchTest);
ScrollableResults cursor = query.scroll();
while ( cursor.next() ) {
Owner owner = (Owner)cursor.get(0);
System.out.println(owner);
}
result of this code is following.
petclinic.domain.Owner@15d616e[id=1,version=0,firstName=Betty,lastName=Davis,
petclinic.domain.Pet@136d9d8[id=2,version=0,name=Basil,birthDate=2002-08-06,
petclinic.domain.PetType@1be2893[id=2,version=0,name=dog]
petclinic.domain.Pet@14a75bb[id=1,version=0,name=Leo,birthDate=2000-09-07,
petclinic.domain.PetType@17779e3[id=1,version=0,name=cat]
petclinic.domain.Owner@e3570c[id=2,version=0,firstName=Eduardo,lastName=Rodriquez
petclinic.domain.Pet@167e3a5[id=4,version=0,name=Jewel,birthDate=2000-03-07,
petclinic.domain.PetType@1926e90[id=4,version=0,name=snake]
First owner object set collection collectly.
but second owner object don't set second pet object(id=5) and third pet object(id=6).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: