2

我正在为 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-context-ref>
    <persistence-context-ref-name>persistence/em</persistence-context-ref-name>
    <persistence-unit-name>pu</persistence-unit-name>
</persistence-context-ref>   

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

由于我是 JPA 的新手,情况很复杂,所以我对底层机制的工作原理没有清晰的了解。因此,任何帮助以及 - 更重要的是 - 对那里发生的事情的解释/链接都将非常感激。谢谢!

4

3 回答 3

2

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

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

有关的:

  1. 默认情况下,实体是否缓存在 jpa 中?
  2. 使 JPA EntityManager 会话无效
于 2010-12-11T11:22:11.693 回答
1

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

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

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

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

于 2010-12-11T11:27:59.637 回答
0

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

于 2010-12-11T11:17:33.803 回答