我正在org.hibernate.LazyInitializationException: illegal access to loading collection
输入我的 JPA 代码 - 所有集合都是 EAGER fetch - 当集合实体也有一个集合时。
有人可以帮我解决这个问题吗?
我已将我的 JPA 代码中的一个问题隔离为以下@Entity
定义:
(注意,我跳过了 package 和 import 语句来缩短代码。使用了一些 Lombok 注释,例如 @Data 表示该字段有一个 getter/setter 和 @Cleanup 来执行通常的 try/catch close()舞蹈)
@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();
}
(如果我明确地做一个 full @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 ,但这似乎是因为load()
抓取了实体的惰性版本。我在这里使用“查找”。我注意到,如果我发出 JPA 查询(而不是 find),那么这个问题就会消失。
find()
更新:如果我使用类似 的查询而不是 ,这确实可以正常工作"SELECT b FROM MyOtherEntity b WHERE b.id = :id"
。也许find()
真的会忽略EAGER
加载!因此,这可能是 Hibernate 中的一个错误。
更新:我已在https://hibernate.onjira.com/browse/HHH-7476将其记录为 Hibernate 的错误报告