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

时间:2010-12-11 10:53:40

标签: java jpa jta

我正在为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>   

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

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

3 个答案:

答案 0 :(得分:2)

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

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

相关:

  1. Are entities cached in jpa by default ?
  2. Invalidating JPA EntityManager session

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:0)

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