2014-10-16 147 views
0

我正在开发一个Vaadin webapp使用JPAContainer与休眠4.3。 我按照这个link的指示,成功地实现了EntityManager-per-Request模式。这意味着懒加载适用于JPAContainerVaadin休眠会话错误

但是,每次我需要使用纯JPA时,它都无法延迟加载。

下面是一个例子代码:

try { 
    entityManagerProvider.getEntityManager().getTransaction().begin(); 

    List<SubEntity> subEntitiesList = myEntity.getCollectionOfEntities(); //Fails to load 

    for (SubEntity subEntity : subEntitiesList) { 
     subEntity.doSomething(); 
     entityManagerProvider.getEntityManager().merge(subEntity); 
    } 
    entityManagerProvider.getEntityManager().flush(); 
    entityManagerProvider.getEntityManager().getTransaction().commit(); 
} catch (Exception ex) { 
    entityManagerProvider.getEntityManager().getTransaction().rollback(); 
} 

//datasource is JPAContainer<MyEntity> type 
datasource.removeItem(index); 

我已经试过这样的解决方案:

  1. 使用hibernate.enable_lazy_load_no_trans 它自动打开的会话,但它给了一个严重警告:

    “无法关闭临时会话用于加载与无会话关联的延迟收集”

此外,当我删除从JPAContainer实体,我收到一个错误:org.hibernate.PersistentObjectException:通过分离的实体坚持

能有人给我如何处理这个问题的一些提示?

回答

1

我看到两种方法。

合并分离实体的变化数据库

刚刚合并实体的管理价值进行操作。

Entity managed = em.merge(entity); 

for (SubEntity sub : managed.getSubEntities()) { 
    sub.doSomething(); 
} 

解决懒代理而不触及DB

查找ID的实体和属性复制到分离的实体。

Entity managed = em.find(entity.getClass(), entity.getId()); 
entity.setSubEntities(managed.getSubEntities()); 

对于第二个选项,我写了一个通用的实用方法来初始化分离的实体在一定深度 ,也许你会觉得它有用。

// initialize lazy collections and collection elements 
JpaUtils.initialize(em, entity, 2); 

查看JpaUtils的源代码。

+0

谢谢何塞!好的答案!最后一个问题:使用第二种方法,如果我使用em.getReference而不是em.find,该怎么办? – guilhermecgs 2014-10-17 13:22:37

+0

@guilhermecgs这很好,特别是如果你只想初始化一些属性。 – 2014-10-18 09:37:05