コレクションエンティティにもコレクションがある場合、JPAコードを取得org.hibernate.LazyInitializationException: illegal access to loading collection
しています-すべてのコレクションはEAGERフェッチです.
誰かがこれを修正するのを手伝ってくれませんか?
JPA コードの問題を次の@Entity
定義に切り分けました。
(コードを短くするために package および import ステートメントをスキップしていることに注意してください。フィールドに getter/setter があることを意味する @Data や、通常の try/catch close() を実行する @Cleanup など、いくつかの Lombok アノテーションが使用されています。ダンス)
@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()
が、エンティティの遅延バージョンを取得しているためと思われます。ここでは「検索」を使用しています。(find ではなく) JPA クエリを発行すると、この問題が解決することに気付きました。
find()
更新: の代わりに のようなクエリを使用すると、これは実際にうまく機能し"SELECT b FROM MyOtherEntity b WHERE b.id = :id"
ます。たぶんfind()
本当にEAGER
読み込みを無視します! したがって、これはおそらく Hibernate のバグです。
更新: https://hibernate.onjira.com/browse/HHH-7476でこれを Hibernate のバグ レポートとして記録しました。