I couldn't find a way to attach the project to this reply; but here is the test case:
class A has bidirectional one-to-many relationship to classes B1, B2, B3, B4
 (b1List, b2List, b3List, b4List)
B1 has bidirectional one-to-many relationship to C1
 (c1List)
B2 has bidirectional one-to-many relationship to C2
 (c2List)
as follows:
Code:
package com.test.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.OptimisticLockType;
@Entity
@AccessType("field")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@org.hibernate.annotations.Entity(optimisticLock=OptimisticLockType.VERSION)
public class A {
   
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   private int id;
   
   private String name;
   
   @OneToMany(fetch = FetchType.LAZY, mappedBy="a", cascade = {CascadeType.PERSIST})
   private Set<B1> b1List;
   
   @OneToMany(fetch = FetchType.LAZY, mappedBy="a", cascade = {CascadeType.PERSIST})
   private Set<B2> b2List;
   
   @OneToMany(fetch = FetchType.LAZY, mappedBy="a", cascade = {CascadeType.PERSIST})
   private Set<B3> b3List;
   
   @OneToMany(fetch = FetchType.LAZY, mappedBy="a", cascade = {CascadeType.PERSIST})
   private Set<B4> b4List;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public Set<B1> getB1List() {
      if(b1List == null)
         b1List = new HashSet<B1>();
      return b1List;
   }
   public void setB1List(Set<B1> list) {
      b1List = list;
   }
   public Set<B2> getB2List() {
      if(b2List == null)
         b2List = new HashSet<B2>();
      return b2List;
   }
   public void setB2List(Set<B2> list) {
      b2List = list;
   }
   public Set<B3> getB3List() {
      return b3List;
   }
   public void setB3List(Set<B3> list) {
      if(b3List == null)
         b3List = new HashSet<B3>();
      b3List = list;
   }
   public Set<B4> getB4List() {
      return b4List;
   }
   public void setB4List(Set<B4> list) {
      if(b4List == null)
         b4List = new HashSet<B4>();
      b4List = list;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   
   
}
Code:
package com.test.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.OptimisticLockType;
@Entity
@AccessType("field")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@org.hibernate.annotations.Entity(optimisticLock=OptimisticLockType.VERSION)
public class B1 {
   
   @Id @GeneratedValue(strategy=GenerationType.AUTO)
   private int id;
   
   @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
   @JoinColumn(name = "aId")
   private A a;
   @OneToMany(fetch = FetchType.LAZY, mappedBy="b1", cascade = {CascadeType.PERSIST})
   private Set<C1> c1List;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public A getA() {
      return a;
   }
   public void setA(A a) {
      this.a = a;
   }
   public Set<C1> getC1List() {
      if(c1List == null)
         c1List = new HashSet<C1>();
      return c1List;
   }
   public void setC1List(Set<C1> list) {
      c1List = list;
   }
}
(other classes are just the same, so I don't copy their code here)
I have entered data in quite all of the tables.
Now, when I run the following code which finds an object of type A, and in its b2List finds an object of type B2, and then adds a C2 to this B2 and persists the C2:
Code:
      A a = em.find(A.class, 1);
      C2 c2 = new C2();
      for(B2 b2:a.getB2List())
      {
         if(b2.getId() == 1)
         {
            b2.getC2List().add(c2);
            c2.setB2(b2);
         }
      }
      em.persist(c2);
Here is what I will see after the line em.persist(c2) is executed:
Code:
16:08:32,296 INFO  [STDOUT] Hibernate: select a0_.id as id0_0_, a0_.name as name0_0_ from A a0_ where a0_.id=?
16:08:32,375 INFO  [STDOUT] Hibernate: select b2list0_.aId as aId1_, b2list0_.id as id1_, b2list0_.id as id2_0_, b2list0_.aId as aId2_0_ from B2 b2list0_ where b2list0_.aId=?
16:08:32,390 INFO  [STDOUT] Hibernate: select c2list0_.b2Id as b2_1_, c2list0_.id as id1_, c2list0_.id as id6_0_, c2list0_.b2Id as b2_6_0_ from C2 c2list0_ where c2list0_.b2Id=?
16:08:32,421 INFO  [STDOUT] Hibernate: select b1list0_.aId as aId1_, b1list0_.id as id1_, b1list0_.id as id1_0_, b1list0_.aId as aId1_0_ from B1 b1list0_ where b1list0_.aId=?
16:08:32,437 INFO  [STDOUT] Hibernate: select c1list0_.b1Id as b2_1_, c1list0_.id as id1_, c1list0_.id as id5_0_, c1list0_.b1Id as b2_5_0_ from C1 c1list0_ where c1list0_.b1Id=?
16:08:32,453 INFO  [STDOUT] Hibernate: select c1list0_.b1Id as b2_1_, c1list0_.id as id1_, c1list0_.id as id5_0_, c1list0_.b1Id as b2_5_0_ from C1 c1list0_ where c1list0_.b1Id=?
16:08:32,453 INFO  [STDOUT] Hibernate: select c2list0_.b2Id as b2_1_, c2list0_.id as id1_, c2list0_.id as id6_0_, c2list0_.b2Id as b2_6_0_ from C2 c2list0_ where c2list0_.b2Id=?
16:08:32,453 INFO  [STDOUT] Hibernate: select c2list0_.b2Id as b2_1_, c2list0_.id as id1_, c2list0_.id as id6_0_, c2list0_.b2Id as b2_6_0_ from C2 c2list0_ where c2list0_.b2Id=?
16:08:32,453 INFO  [STDOUT] Hibernate: select c2list0_.b2Id as b2_1_, c2list0_.id as id1_, c2list0_.id as id6_0_, c2list0_.b2Id as b2_6_0_ from C2 c2list0_ where c2list0_.b2Id=?
16:08:32,453 INFO  [STDOUT] Hibernate: select c2list0_.b2Id as b2_1_, c2list0_.id as id1_, c2list0_.id as id6_0_, c2list0_.b2Id as b2_6_0_ from C2 c2list0_ where c2list0_.b2Id=?
16:08:32,468 INFO  [STDOUT] Hibernate: select b3list0_.aId as aId1_, b3list0_.id as id1_, b3list0_.id as id3_0_, b3list0_.aId as aId3_0_ from B3 b3list0_ where b3list0_.aId=?
16:08:32,468 INFO  [STDOUT] Hibernate: select b4list0_.aId as aId1_, b4list0_.id as id1_, b4list0_.id as id4_0_, b4list0_.aId as aId4_0_ from B4 b4list0_ where b4list0_.aId=?
16:08:32,531 INFO  [STDOUT] Hibernate: insert into C2 (b2Id) values (?)
The question is, if I am persisting C2, why is it initializing C1 or B4, or other existing C2's?
In our application as the relationships are more complicated and there is a lot of data, this will result in a timeout, so that in some cases it never reaches the very last line (insert).
Thanks for your time