【发布时间】:2012-07-21 04:58:15
【问题描述】:
我在我的 JPA 代码中收到 org.hibernate.LazyInitializationException: illegal access to loading collection - 所有集合都是 EAGER fetch - 当集合实体也有一个集合时。
有人可以帮我解决这个问题吗?
我已将我的 JPA 代码中的一个问题隔离为以下 @Entity 定义:
(注意,我跳过了 package 和 import 语句来缩短代码。使用了一些 Lombok 注释,例如 @Data 表示该字段具有 getter/setter 和 @Cleanup 来执行通常的 try/catch关闭()舞蹈)
@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();
}
(如果我明确地执行完整的@JoinTable,我也会遇到同样的问题,但是如果没有它,Hibernate 似乎可以生成一切正常 - 我很高兴将它排除在外)。
问题是,如果我取消注释@MyEntity 中的“标签”字段,那么我总是得到以下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)
下面是一个简短的应用程序来举例说明这个问题:
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();
}
}
更新:我知道LazyInitializationException when field is eager,但这似乎是因为load() 获取了实体的惰性版本。我在这里使用“查找”。我注意到,如果我发出 JPA 查询(而不是 find),那么这个问题就会消失。
更新:如果我使用"SELECT b FROM MyOtherEntity b WHERE b.id = :id" 之类的查询而不是find(),这确实可以正常工作。也许find() 确实忽略了EAGER 加载!因此,这可能是 Hibernate 中的一个错误。
更新:我已将此作为 Hibernate 的错误报告记录在 https://hibernate.onjira.com/browse/HHH-7476
【问题讨论】:
-
代码的哪一行抛出了异常?只是为了确定:如果没有
tags字段,这段代码可以按预期工作吗? -
是的,无需标签即可工作。异常是在 find() 方法调用上。
标签: java hibernate jpa persistence