JPA CascadeType.REFRESH不工作?

时间:2010-10-22 12:27:42

标签: java jpa

我遇到了JPA CascadeType.REFRESH属性的一个奇怪问题。 我有一个简单的父子关系,在父域对象(LineEquipmentFormat)中我添加了如下的级联属性

OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST,
   CascadeType.REMOVE}, mappedBy = "lineEquipmentFormat")
 public List<LineEquipmentFormatDivision> getLineEquipmentFormatDivisions() {
  return lineEquipmentFormatDivisions;
 }

但是当我从DB获取父LineEquipmentFormat对象时,我没有得到LineEquipmentFormatDivisions的列表。

我得到的错误是

  17:46:34,251 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed
     at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
     at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
     at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
     at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
     at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506)

我使用的是Jboos 5.1和Oracle 10G。

请提供有关此错误的可能根本原因的更多输入。

由于

3 个答案:

答案 0 :(得分:2)

当您将级联类型定义为刷新时,这意味着在父LineEquipmentFormat上调用entityManager.refresh()时,它也将在子LineEquipmentFormatDivisions上调用。但是,您收到的错误表示您在会话关闭时尝试懒惰地初始化集合。如果在会话关闭后需要此集合,则需要通过设置fetchType来急切地获取它们。

答案 1 :(得分:1)

  

我添加了如下的级联属性(...)但是当我从DB获取父级LineEquipmentFormat对象时,我没有得到LineEquipmentFormatDivisions的列表。

级联操作与EAGER或LAZY加载几乎没有关系,在你的情况下,你得到的错误(臭名昭着的LazyInitializationException)意味着你试图访问一个懒惰的关联但是会话已经被关闭(所以Hibernate无法加载它)。

要避免这个“问题”,请:

  • 急切地使用fetchType属性加载关联(如果你在大多数情况下不需要关联,那就是IMO将“口红放在猪身上”)
  • 在执行查询时使用FETCH JOIN来获取此特定用例,例如:

    SELECT f
    FROM LineEquipmentFormat f LEFT JOIN FETCH f.lineEquipmentFormatDivisions
    WHERE f.id = 1
    
  • 使用 Open EntityManager In View 模式(在MVC上下文中)在请求进入时打开实体管理器并保持打开直到请求处理完毕(Spring有一个实现此模式的Serlvet filterInterceptor)。

答案 2 :(得分:0)

感谢您的评论。

以下是我们最终如何实施它。

  1. 在获取“LineEquipmentFormat”父对象时,我们添加了以下附加代码。

    LineEquipmentFormat lef = entityManager.find(LineEquipmentFormat.class,sysId);         if(lef!= null&amp;&amp; lef.getLineEquipmentFormatDivisions()!= null){             。lef.getLineEquipmentFormatDivisions()大小();         }
            返回lef;

  2. 现在我们可以从这个父对象中获取子列表。