I've encountered some seemingly counter-intuitive behavior when mixing eager and lazy loading of associations. Consider these entities:
Code:
@Entity
@Table(name = "parent")
public class Parent {
@Id
@Column(name = "id")
private Long id;
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
private List<Child> children;
public Long getId( ) { return id; }
public void setId( Long id ) { this.id = id; }
public List<Child> getChildren( ) { return children; }
public void setChildren( List<Child> children ) { this.children = children; }
}
@Entity
@Table(name = "child")
public class Child {
@Id
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Parent parent;
public Long getId( ) { return id; }
public void setId( Long id ) { this.id = id; }
public Parent getParent( ) { return parent; }
public void setParent( Parent parent ) { this.parent = parent; }
}
Now consider this code:
Code:
@Stateless
@LocalBean
public class TestBean {
@PersistenceContext
private EntityManager em;
@TransactionAttribute(value = TransactionAttributeType.SUPPORTS)
public String test1( ) {
String s = "";
Child c = em.find( Child.class, 1L );
Parent p = c.getParent( );
List<Child> children = p.getChildren( );
for( Child child : children ) {
s += child.getId( ) + "\n";
}
return s;
}
}
The above code throws a LazyInitializationException at runtime because p.children is lazily fetched even though the entity definition of Parent declares children to be eagerly fetched. Changing the fetch type of Child#parent to eager avoids the issue, as does "expanding" the scope of the transaction (e.g. using TransactionAttributeType.REQUIRED). Also, loading the desired instance of Parent directly (using EntityManager#find) works without issue.
Is this normal behavior? For comparison, EclipseLink (bundled with Glassfish v3) does not throw any exceptions with the exact same code. It seems odd that the fetching behavior for Parent#children would be affected by the route taken to acquire the reference to the Parent entity, but perhaps I'm missing something here. Any insights would be greatly appreciated.