I can't seem to get a trivial unidirectional oneToMany relationship to work properly. I write an object in a session, then I merge that object in another session and add something to its collection. Then I load that object in a third session and read the collection, but it is empty. I have a JUnit test below which fails on the assertEquals() with an "Expected 1, but was 0".
Hibernate version:
3.2.0GA (as packaged with JBoss 4.0.5 GA)
Name and version of the database you are using:
HSQL Database Engine, version: 1.8.0
Entities:
Code:
@Entity
public class A {
@Id
@GeneratedValue
private long jpaId;
@OneToMany(cascade = CascadeType.ALL)
private Collection<B> bCollection;
public A() { this.bCollection = new ArrayList<B>(); }
public void addB(B b) { this.bCollection.add(b); }
public Collection<B> getBCollection() { return bCollection; }
private void setBCollection(Collection<B> collection) { bCollection = collection; }
public long getJpaId() { return jpaId; }
private void setJpaId(long jpaId) { this.jpaId = jpaId; }
}
Code:
@Entity
public class B {
@Id
@GeneratedValue
private long jpaId;
private String description;
public B() {}
public B(String description) { this.description = description; }
private String getDescription() { return description; }
private void setDescription(String description) { this.description = description; }
private long getJpaId() { return jpaId; }
private void setJpaId(long jpaId) { this.jpaId = jpaId; }
}
Code between sessionFactory.openSession() and session.close():Code:
public class CascadeTest {
@Test
public void testCascade() {
// setup
A a = new A();
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("CascadeProblem");
EntityManager manager = emf.createEntityManager();
EntityTransaction tx1 = manager.getTransaction();
tx1.begin();
manager.persist(a);
tx1.commit();
manager.close();
// execute
EntityManager manager2 = emf.createEntityManager();
EntityTransaction tx2 = manager2.getTransaction();
tx2.begin();
manager2.merge(a);
B b = new B("b1");
a.addB(b);
tx2.commit();
manager2.close();
// verify
EntityManager manager3 = emf.createEntityManager();
EntityTransaction tx3 = manager3.getTransaction();
tx3.begin();
A loadedA = manager3.find(A.class, a.getJpaId());
Collection<B> accountEntries = loadedA.getBCollection();
assertEquals(1, accountEntries.size());
assertTrue(accountEntries.contains(b));
tx3.commit();
manager3.close();
}
}
Debug level Hibernate log excerpt:Code:
22:29:11,531 DEBUG ConnectionManager:84 - opening JDBC connection
22:29:11,562 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: insert into A (jpaId) values (null)
22:29:11,562 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:29:11,562 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: call identity()
22:29:11,562 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:29:11,578 DEBUG ConnectionManager:84 - aggressively releasing JDBC connection
22:29:11,578 DEBUG ConnectionManager:84 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
22:29:11,578 DEBUG ConnectionManager:84 - opening JDBC connection
22:29:11,593 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: select a0_.jpaId as jpaId0_1_, bcollectio1_.A_jpaId as A1_3_, b2_.jpaId as bCollect2_3_, b2_.jpaId as jpaId1_0_, b2_.description as descript2_1_0_ from A a0_ left outer join A_B bcollectio1_ on a0_.jpaId=bcollectio1_.A_jpaId left outer join B b2_ on bcollectio1_.bCollection_jpaId=b2_.jpaId where a0_.jpaId=?
22:29:11,593 DEBUG AbstractBatcher:84 - about to open ResultSet (open ResultSets: 0, globally: 0)
22:29:11,593 DEBUG AbstractBatcher:84 - about to close ResultSet (open ResultSets: 1, globally: 1)
22:29:11,593 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:29:11,609 DEBUG ConnectionManager:84 - aggressively releasing JDBC connection
22:29:11,609 DEBUG ConnectionManager:84 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
22:29:11,609 DEBUG ConnectionManager:84 - opening JDBC connection
22:29:11,609 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: select a0_.jpaId as jpaId0_0_ from A a0_ where a0_.jpaId=?
22:29:11,609 DEBUG AbstractBatcher:84 - about to open ResultSet (open ResultSets: 0, globally: 0)
22:29:11,609 DEBUG AbstractBatcher:84 - about to close ResultSet (open ResultSets: 1, globally: 1)
22:29:11,609 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
22:29:11,609 DEBUG AbstractBatcher:84 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: select bcollectio0_.A_jpaId as A1_1_, bcollectio0_.bCollection_jpaId as bCollect2_1_, b1_.jpaId as jpaId1_0_, b1_.description as descript2_1_0_ from A_B bcollectio0_ left outer join B b1_ on bcollectio0_.bCollection_jpaId=b1_.jpaId where bcollectio0_.A_jpaId=?
22:29:11,625 DEBUG AbstractBatcher:84 - about to open ResultSet (open ResultSets: 0, globally: 0)
22:29:11,625 DEBUG AbstractBatcher:84 - about to close ResultSet (open ResultSets: 1, globally: 1)
22:29:11,625 DEBUG AbstractBatcher:84 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)