0

我在这里遇到了一个非常奇怪的情况。当我尝试删除一组实体并稍后立即尝试添加另一组实体时,这些实体可能会或可能不会再次具有相同的元素,我似乎遇到了以下异常。不需要整个堆栈跟踪,因为它并没有说太多。

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也没有用。jpaEntityManager似乎也没有commit()方法,我可以在方法delete()之前的 & 之后使用它store()。我也尝试过store()persist()(尽管商店内部调用persist())交换!

注意:-要求是删除旧列表并插入新列表,因为比较元素并仅添加新元素很乏味(有时列表可能非常大)。

4

2 回答 2

2

我认为例外情况很明显:您告诉会话删除实体 X 并同时存储实体 X。现在可怜的东西很困惑,不知道该怎么办。

在持久化新/旧/已删除实体之前Session.flush()可能通过 a进行操作。commit

编辑:

如果这不起作用,您需要在新会话中进行插入。问题可能仍然是,您没有临时实体,但实际上已删除。因此,您可能必须将所有数据复制到一个新实例中。

于 2013-05-13T05:44:32.843 回答
0

我已经想出了一个办法。我使用flushAndClear()方法而不是flush()方法。

似乎flush()唯一将持久性缓存与数据库同步但没有清除它。

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

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

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

您可以做两件事,将所有 PK 删除放在一起,然后在完成后调用 flushAndClear,或者您可以只使用不会遇到此问题的实体调用 delete 方法。

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

于 2013-05-13T06:26:28.570 回答