0

这是顺序:

  1. App1:在 ID=1 的数据库上持久化实体。没问题。
  2. App2:外部应用程序删除 ID=1 的同一记录。没问题。
  3. App1:尝试再次持久化之前被App2删除的实体,这里抛出一个异常“IntegrityConstraintViolation”,好像记录还在数据库中,我插入了两次,不是。

事实是,正如我所见,EntityManager 正在使用缓存来验证数据库的完整性。不知何故,即使在我打电话之后

getEM().getEntityManagerFactory().getCache().evictAll(); or getEM().clear();

EntityManager 以某种方式将该记录保存在缓存中,而我对如何清除该缓存没有任何想法。我发现的一种解决方法是从 App1 调用:

getEM().remove(entity.class, id);

它还有效地从数据库和 EntityManager 缓存中删除了记录。但是,这不是重点,它只是证明它正在使用缓存进行验证,但主要问题仍然存在,“从另一个应用程序中删除后,我无法再次持久化记录”。

顺便说一句,我也尝试刷新实体,但也不起作用。它抛出一个异常,说该实体不受管理。

有人对如何解决这个问题有任何想法吗?

4

2 回答 2

1

App2 是否提交事务?

IntegrityConstraintViolation 是从数据库中抛出的,因此它意味着旧行仍然存在于数据库中。

最好打开日志记录并包括两个应用程序的日志和完整的异常堆栈跟踪。

一般来说,转世对象通常不是一个好主意。最好创建一个具有新 id 的新对象,或者至少分离/复制到旧对象。

如果另一个应用程序正在访问同一个数据库,您可以考虑禁用缓存,

http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F

否则,如果您只想刷新此对象的缓存,请先调用 find() 以确保该对象是托管的,然后调用 refresh() 将其从共享缓存中删除。(然后您需要分离()它,或清除()您的 EntityManager 或创建一个新的)。

于 2013-06-26T13:59:46.570 回答
0

终于解决了这个问题,这个版本的 EclipseLink 2.5 的行为与以前的版本有点不同,这就是不同之处之一。问题是我在 TestClass 的 'tearDown()' 方法中执行了这一行:

em.CreateQuery("delete from mytable").executeUpdate();

清理数据库中的表。即使这一行有效地从数据库中删除了记录,如果您使用相同的 EntityManager,那么无论您做什么,它都不会从缓存中删除它。所以,我只是移动了查询并在mytable Entity 类中创建了一个@NamedQuery注释,并调用了 NamedQuery 而不是直接执行 SQL。所以,我在“tearDown()”方法中的代码最终是:

em.CreateNamedQuery("emptyMyTableQuery").executeUpdate();

还有@NamedQuery:

@NamedQuery(name="emptyMyTableQuery", query="delete from mytable")

现在它完美地工作了。

老实说,即使在以前的 EclipseLink 版本中没有发生这种情况,我不得不说这个新版本 2.5 在几个方面有一些增强和改进,也修复了一些错误。好吧,希望这有助于有人发现同样的问题。

于 2013-06-27T02:53:13.260 回答