I am getting org.hibernate.LazyInitializationException: illegal access to loading collection
in my JPA code - all collections are EAGER fetch - when the collection entity also has a collection.
Could somebody please help me to fix this?
I have isolated a problem in my JPA code to the following @Entity
definitions:
(note, I'm skipping the package and import statements to shorten the code. Some Lombok annotations are used, such as @Data to mean that the field has a getter/setter and @Cleanup to do the usual try/catch close() dance)
@Entity
@Data
public class MyEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// @ElementCollection(fetch = FetchType.EAGER)
// private Set<String> tags = Sets.newTreeSet();
}
@Entity
@Data
public class MyOtherEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToMany(fetch = FetchType.EAGER)
private Set<MyEntity> entities = Sets.newHashSet();
}
(I also get the same problem if I explicitly do a full @JoinTable
, but Hibernate seems to generate everything fine without it - I'm happy leaving it out).
The problem is that if I uncomment the "tags" field in @MyEntity
, then I always get the following PersistenceException
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:828)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:781)
The following is a short application which exemplifies the problem:
public class JpaQuestion {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("hibernate.connection.driver_class", "org.apache.derby.jdbc.EmbeddedDriver");
properties.put("hibernate.connection.url", "jdbc:derby:playground;create=true");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PlaygroundPU", properties);
populate(emf);
@Cleanup("close") EntityManager em = emf.createEntityManager();
MyOtherEntity other = em.find(MyOtherEntity.class, 1L);
System.out.println(other != null ? other.toString() : "null");
}
public static void populate(EntityManagerFactory emf) {
@Cleanup("close") EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MyEntity a = new MyEntity();
em.persist(a);
MyOtherEntity other = new MyOtherEntity();
other.getEntities().add(a);
em.persist(other);
em.getTransaction().commit();
}
}
UPDATE: I know about LazyInitializationException when field is eager but that seems to be because load()
grabs a lazy version of the entity. I'm using "find" here. I've noticed that if I issue a JPA query (instead of find), then this problem goes away.
UPDATE: This really does work fine if instead of find()
, I use a Query like "SELECT b FROM MyOtherEntity b WHERE b.id = :id"
. Maybe find()
really does ignore EAGER
loading! Hence this is likely a bug in Hibernate.
UPDATE: I've logged this as a bug report with Hibernate at https://hibernate.onjira.com/browse/HHH-7476