EntityManager不会看到在其他事务中所做的更改

我正在为GlassFish 2.1.1(JavaEE 5,JPA 1.0,据我所知)编写一些应用程序。 我的servlet中有以下代码(我主要借用Internet上的一些示例):

@PersistenceContext(name = "persistence/em", unitName = "pu") private EntityManager em; @Resource private UserTransaction utx; @Override protected void doPost(...) { utx.begin(); . . . perform retrieving operations on em . . . utx.rollback(); } 

web.xml包含以下内容:

  persistence/em pu  

问题是,em没有看到在另一个外部事务中所做的更改。 粗略地说,我从Web浏览器向我的servlet发出请求,查看数据,在SQL控制台中执行一些DML,重新加载servlet页面 – 并且它没有显示任何更改。 我试过使用em.flushutx.rollbackem.joinTransaction许多组合,但它似乎没有任何好处。

由于我是JPA的新手,所以情况变得复杂,因此我对底层机械的工作原理并不清楚。 所以任何帮助 – 更重要的是 – 对那里发生的事情的解释/链接将非常感激。 谢谢!

JPA实现维护已访问的实体的缓存。 当您在不使用JPA的情况下在不同的事务中执行操作时,缓存不再是最新的,因此您永远不会看到其中所做的更改。

如果您确实希望查看更改,则必须刷新缓存,在这种情况下,所有实体都将从缓存中逐出。 当然,您需要知道何时执行此操作(在其他事务完成之后),否则您将继续看到不明确的实体。 如果这是您的业务需求,那么JPA可能不适合您的问题域。

有关:

  1. 实体是否默认缓存在jpa中?
  2. 使JPA EntityManager会话无效

正如axtavt所说,您需要在控制台中提交事务。 假设您这样做了,PersistenceManager(或底层基础架构)仍然可以缓存数据。

为了防止缓存问题,您可以手动逐出(这可能很棘手,因为您必须知道何时驱逐)或者您可以进行悲观锁定。 悲观锁定会对性能产生巨大影响,但如果您有多个与数据库的独立连接,则可能无法选择。

如果你的进程一直有来自不同源的并发读/写,你可能真的需要悲观锁。 如果您有时从外部源进行批量更新,您可能会尝试从该批处理作业发出它应该驱逐的JPA应用程序的信号。 也许是通过网络服务等。 这样,您不会在整个时间内导致悲观的锁定性能下降。

这里明智的教训是,进程的同步可能非常复杂:)

也许您需要提交在SQL控制台中进行的事务。