【问题标题】:Java EE 6 + Hibernate Lazy load exceptionJava EE 6 + Hibernate 延迟加载异常
【发布时间】:2012-05-21 17:13:29
【问题描述】:

这就是我卡住的地方:

javax.servlet.ServletException: org.hibernate.LazyInitializationException:延迟初始化失败 角色集合:it.trew.model.TipoCaratteristica.traduzioni,无 会话或会话已关闭

我的一些实体代码:

@Entity
@Table(name = "tipi_caratteristiche")
public class TipoCaratteristica implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    private String nome;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(
        name = "tipi_caratteristiche_traduzioni", 
        joinColumns = { @JoinColumn(name = "tipo_caratteristica_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "traduzione_id") }
    )
    private List<Traduzione> traduzioni = new ArrayList<Traduzione>();

“Traduzione”是一个简单的普通实体,带有一对字符串属性。

我有一个“编辑”jsf 页面,它通过 id 加载“TipoCaratteristica”并尝试在标签中显示其列表。

我使用 ejb-facade 方法来获取已编辑的对象:

public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

然后,在 jsf 支持 bean 中:

TipoCaratteristica tc = ejbFacade.find(Long.valueOf(value));

我读到了一些关于那个异常的东西。实际上,在“traduzioni”集合上设置获取类型 EAGER 可以修复它,但我不想这样做。 我读过关于在事务中做所有事情,或使用 Hibernate.initialize() 但不知道如何做到这一点。

你能帮帮我吗?

【问题讨论】:

    标签: hibernate jakarta-ee jpa ejb


    【解决方案1】:
    @Override
    public TipoCaratteristica find(Object id) {
        TipoCaratteristica result = super.find(id);
        Hibernate.initialize(result.getTraduzioni());
        return result;
    }
    

    或者不使用em.find(),而是使用将加载所有内容的查询是单个查询:

    select distinct tc from TipoCaratteristica 
    left join fetch tc.traduzioni
    where tc.id = :id
    

    【讨论】:

    • 您的 EJB 外观似乎有一个基本参数化类,并且每个实体都有该 EJB 外观的一个子类。上述被覆盖的方法应该在 TipoCaratteristica 实体的 EJB 外观中。如果我的假设是错误的,请发布您的代码。
    • 好的。我必须记住 initialize() 必须在 EJB 方法中完成,不是吗?
    • 必须在事务中会话仍然打开的地方完成。如果您在会话关闭后执行此操作,您显然会得到相同的延迟加载异常。
    【解决方案2】:

    您可以在实体管理器中使用 PersistentContext.EXTENDED 属性解决此问题。

    例子:

    @PersistentContext(type=PersistentContext.EXTENDED)
    private EntityManager em; 
    

    或更新版本:

    @PersistentContext(type=PersistentContextType.EXTENDED)
    private EntityManager em; 
    

    发生此错误是因为对于每个事务,实体管理器事务都已关闭,此属性可避免这种情况并允许实体管理器保持可用。您可以阅读 Dan Allen 的 Seam in Action 一书了解更多详细信息,他详细解释了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 2011-07-25
      • 2018-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多