为什么实体会分离以及如何处理它?

时间:2013-10-01 08:58:26

标签: java-ee jpa

何时

  1. 我通过无状态服务从数据库中获取实体
  2. 然后在另一个bean中修改它
  3. 然后想通过无状态服务将其保存到数据库,
  4. 我注意到该实体已被分离。我认为因为无状态服务的持久化上下文,实体来自于抓住存在。 但是,如果使用有状态服务吗? 现在保存时我使用EntityManager#find(ClassOfDetachedEntity,PrimaryKeyOfDetachedEntity)来获取对数据库中实体的引用,然后将分离的实体分配给它。
    但是这样吗?
    在我只复制数据库之前,我只是想修改现有的条目。

    更新(显示“分离”问题出现位置的快速示例):

    @Stateless
    @Log
    public class DatabaseService implements Serializable {
    
        @PersistenceContext
        EntityManager em;
    
        public List<Category> getCategories() {
            return em.createQuery("SELECT c FROM Category c").getResultList();
        }
    
        public void checkIfDetached(Object o){
            log.info("is detached: " + String.valueOf(!em.contains(o)));
        }
    }  
    

    beans log-statement会告诉我,对象是分离的:

     @ManagedBean
        @ViewScoped
        public class CategoriesBean implements Serializable {
            private Category testCategory;
    
            @PostConstruct
            public void init(){
                testCategory = dbs.getCategories().get(0);
                dbs.checkIfDetached(testCategory);
            }
        }
    

3 个答案:

答案 0 :(得分:1)

有些原因是:

  1. 您在步骤2中使用@Remote EJB而不是@Local。
  2. 第一个EJB的事务上下文与第二个EJB的事务上下文不同。
  3. 易于理解的是,一旦事务关闭(提交或回滚),实体就会被解除。

    我没有使用JSF的经验,但我认为一旦你在JSF中调用ejb.getCategories(),EJB中的事务就会完成,因此实体会被释放。你也没有展示你是如何注入dbs的:我希望你使用@EJB来做到这一点。此外我已经读过(至少@ManagedBean -annotated )JSF不是(默认?)事务性的。

答案 1 :(得分:1)

这可能发生,因为当您调用getCategories时,因为没有事务而启动了新事务。当函数退出时,该事务已完成且所有实体都已分离。确保您在一次交易中完成所有步骤。

答案 2 :(得分:1)

分离的实体并不是什么大不了的事,你知道,你可以轻松地将其附加回来。实际上,如果我记得从 EJB 3 in Action 中解脱出来,那么JPA的设计应该以尽可能 short 时间附加实体。

在对其执行任何JPA操作之前,只需merge(将其附加)您的实体:

em.merge(entity);