2013-05-13 81 views
0

我遇到了一个非常奇怪的情况。当我尝试在后面立即删除一组实体&时尝试添加另一组实体,这些实体可能也可能不再有相同的元素,我似乎正在获得以下例外。整个堆栈跟踪不是必需的,因为它不会说太多。解决JPA/Hibernate EntityNotFoundException

javax.persistence.EntityNotFoundException: deleted entity passed to persist [com.test.MyEntity#<null>] 

为了让自己更清楚,让我给出更详细的解释。

这是我的实体。

@Entity 
@Table(name = "MY_ENTITY") 
@SequenceGenerator(name = "my_enty_seq", sequenceName = "MY_ENTITY_SEQ") 
public class MyEntity { 

    private long id; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_enty_seq") 
    @Column(name = "ID", unique = true, nullable = false, precision = 12, scale = 0) 
    public long getId() { 
     return this.id; 
    } 

    // Other methods & variables which are not relevant here. 
} 

这是玩实体的类。

public class MyEntityServiceImpl implements MyEntityService { 

    public void updateMyEntities(List<MyEntity> newEntities) { 

     // Delete the Old Items 
     List<MyEntity> oldEntities = myDAO.getAllEntities(); 
     myDAO.delete(oldEntities); // myDAO extends GenericDaoJpaWithoutJpaTemplate, hence, the DELETE is available in it. 

     // Add the New Items 
     myDAO.store(newEntities); // This is where I get the mentioned Exception. 
    } 

    // Other non-relevant stuffs 
} 

从哪里获得的store()方法所提到的例外的情况是有一些共同的MyEntity对象,同时存在于oldEntitiesnewEntities名单。

我已经尝试了很多事情来完成这项工作,但没有任何东西可以帮助我解决问题。添加FetchType.EAGER & CascaseType.ALL, CascaseType.PERSIST也没有工作。 jpa EntityManager似乎也没有commit()方法,我可以在store()方法之前的delete() &之后使用。我试过与交换store()(虽然店内也叫persist())!

注意: -需要删除旧列表并插入新列表,因为比较元素并只添加新元素是很繁琐的(列表可能有时非常庞大)。

回答

0

我已经想出了一个办法。我用flushAndClear()方法代替flush()方法。

看起来flush()只将持久性缓存与数据库同步,但没有清除它。

flushAndClear()另一方面执行所有挂起的操作,然后清除everthing。

从存在于org.crank.crud.GenericDao<T, PK extends Serializable>为删除方法的源代码的Java文档引用,

删除从数据库中的持久存储器中的对象。由于此 使用PK执行删除,因此如果删除对象为 id 1但实体管理器 可能会处于不一致状态,但该对象仍在实体管理器缓存中。

你可以做两件事情,把你所有的PK将删除在一起,然后调用 flushAndClear完成时,或者你可以调用delete方法与 ,不会存在这个问题的实体。

我试着使用flushAndClear()方法的第一个选项,它按预期工作。

2

这个例外很明显我想:你告诉会话删除实体X,同时存储实体X.现在可怜的东西很困惑,不知道该怎么做。

在坚持新/旧/删除实体之前,可能通过commit执行Session.flush()

编辑:

如果不这样做的伎俩,你需要做插入一个新的会话。问题可能仍然是,你没有一个短暂的实体,但实际上删除了一个。因此,您可能必须将所有数据复制到新实例中。

+0

一个提交只是在实际提交事务之前进行刷新。 – 2013-05-13 05:52:47