EntityManager看不到其他事务中所做的更改
我正在为 GlassFish 2.1.1(据我所知,JavaEE 5、JPA 1.0)编写一些应用程序。我的 servlet 中有以下代码(我主要是从互联网上的一些示例借用的):
@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
和 em.joinTransaction
的多种组合,但似乎没有做任何好事。
由于我是 JPA 的新手,情况很复杂,所以我对底层机制的工作原理并不清楚。因此,任何帮助,以及 - 更重要的是 - 对正在发生的事情的解释/链接将非常感激。谢谢!
I'm writing some application for GlassFish 2.1.1 (JavaEE 5, JPA 1.0, as far as I know). I have the following code in my servlet (which I mostly borrowed from some sample on the 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
has the following in it:
<persistence-context-ref>
<persistence-context-ref-name>persistence/em</persistence-context-ref-name>
<persistence-unit-name>pu</persistence-unit-name>
</persistence-context-ref>
The problem is, the em doesn't see changes that have been made in another, outside transaction. Roughly, I make a request to my servlet from web browser, see data, perform some DML in SQL console, reload servlet page -- and it doesn't show any change. I've tried to use many combinations of em.flush
, and utx.rollback
, and em.joinTransaction
, but it doesn't seem to do any good.
Situation is complicated by me being a total newbie in JPA, so I do not have a clear understanding of how the underlying machinery works. So any help and -- more importantly -- explanations/links of what is happening there would be very appreciated. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
JPA 实现维护已访问实体的缓存。当您在不使用 JPA 的情况下在不同事务中执行操作时,缓存将不再是最新的,因此您永远不会看到其中所做的更改。
如果您确实希望看到更改,则必须刷新缓存,在这种情况下,所有实体都将从缓存中逐出。当然,您需要知道何时执行此操作(在其他事务完成之后),否则您将继续看到不明确的实体。如果这是您的业务需求,那么 JPA 可能不太适合您的问题领域。
相关:
The JPA implementation maintains a cache of entities that have been accessed. When you perform operations in a different transaction without using JPA, the cache is no longer up to date, and hence you never see the changes made in it.
If you do wish to see the changes, you will have to refresh the cache, in which case all entities will be evicted from the cache. Of course, you'll need to know when to do this (after the other transaction has completed), otherwise you'll continue to see ambiguous entities. If this is your business need, then JPA is possibly not a good fit to your problem domain.
Related:
正如 axtavt 所说,您需要在控制台中提交事务。假设您这样做了,PersistenceManager(或底层基础设施)也可能仍在缓存数据。
为了防止缓存出现问题,您可以手动逐出(这可能很棘手,因为您必须知道何时逐出),或者可以使用悲观锁定。悲观锁定会对性能产生巨大影响,但如果您有多个独立的数据库连接,您可能别无选择。
如果您的进程始终有来自不同来源的并发读/写,您可能确实需要悲观锁。如果您有时从外部源进行批量更新,您可能会尝试从该批处理作业向您的 JPA 应用程序发出它应该驱逐的信号。也许通过网络服务等。这样您就不会一直遭受悲观锁定性能下降。
这里的明智教训是进程的同步可能非常复杂:)
As axtavt says, you need to commit the transaction in the console. Assuming you did that, it is also possible data is still being cached by the PersistenceManager (or underlying infrastructure).
To prevent trouble with caching you can evict by hand (which may be tricky as you have to know when to evict) or you can go to pessimistic locking. Pessimistic locking can have a huge impact on performance, but if you have multiple independent connections to the database you may not have a choice.
If your process has concurrent read/writes from different sources the whole time, you may really need pessimistic locks. If you sometimes have a batch update from an external source, you may try to signal, from that batch job, your JPA application that it should evict. Perhaps via a web service or so. That way you would not incur pessimistic locking performance degradation the entire time.
The wise lesson here is that synchronization of processes can be really complicated :)
也许您需要提交在 SQL 控制台中进行的事务。
Perhaps you need to commit a transaction made in SQL console.