旧的“org.hibernate.LazyInitializationException ...无法初始化代理 - 没有会话”:不明白为什么

时间:2014-02-11 00:40:37

标签: java hibernate jsf

我收到了LazyInitializationException并且不确定原因。我将一个实体(具有id的BaseEntity)作为数据存储在primefaces树节点上,以使其成为动态的(即onNodeExpand事件处理程序从db获取扩展节点子节点)。我知道实体在渲染后变得分离,这就是为什么我在onNodeExpand中执行以下操作来添加子节点:

    Product parentProduct = productService.findById(entity.getId());

这是返回一个我认为会“附加”的实体,但是当我迭代一个延迟加载的OneToMany关系时,我得到了LazyInitializationException:

    for (Module module: parentProduct.getModules()) {

我在这里不明白?

修改

ProductService是一个@Stateless EJB,如下所示注入ViewScoped Bean:

@Named
@ViewScoped
public class MasterBean implements Serializable {
    private static final long serialVersionUID = 3153934047649103375L;

    TreeNode root;

    @EJB
    ProductRepo productService;

findById位于通用的CrudRepository中:

    public E findById(final K id) {
            return em.find(entityClass, id);
    }

2 个答案:

答案 0 :(得分:0)

如果您没有明确定义FetchType的Product和Modules之间存在OneToMany关系,那么获取类型by default is Lazy。如果是这种情况,那么你需要确保在Hibernate会话中迭代加载延迟的集合。

Hibernate会话有很多可以定义Hibernate会话的分界线,特别是当你使用库/框架时。我不熟悉primefaces,但如果你read up on Hibernate sessions here,你可能会看到Hibernate会话如何使用它。

答案 1 :(得分:0)

我遇到了与我正在开发的系统完全相同的问题。要解决此问题,您需要做的是获取包含该集合的对象,然后在同一会话中访问该集合,如下所示:

@Transactional
public User retrieveUser(String username)
{
    User user = hibernateUserDao.getUserByUsername(username) 
    /*whatever your method of getting something from the database */

    Collection collection = user.getCollection();
    /*Then you can access and manipulate the collection object*/
}

这是因为如果你检索用户对象,默认情况下不会出于性能原因检索集合,但如果你在一个事务中全部执行,那么数据库连接仍然存在,所以hibernate会去检索实例你的收藏。

另一个缺陷是尝试在一个事务中检索用户,然后启动一个新用户来访问您的集合对象。 Hibernate不允许你这样做,它会引发类似的错误。

告诉我这是否有意义。

TL; DR:您必须检索父对象,然后在同一事务会话中访问您的集合对象。