【发布时间】:2016-10-12 19:44:30
【问题描述】:
我有一个使用 Eclipselink 实现的 JPA 的 Java EE 应用程序。我已经使用 ExternalContext 会话映射实现了一个基本的用户登录系统。但是,似乎会话经常与数据库不同步。
基本流程是 1. 用户 A 创建一个 BidOrder 实体。 2. 用户 B 创建一个 AskOrder 实体。 3. 监视器检查两个订单是否匹配,如果匹配,则创建一个 OrderBook 实体 4. 将更改推送给所有用户(使用 Primefaces 5.3 Push)
当我检查价格时,我在我的 SessionScoped 支持 bean 中使用此方法作为我的主视图:
public void findLatestPrices()
{
logger.log(Level.INFO, "findLatestPrices with user {0} ",user.getUserId());
findAllOrderBooks();
latestPricesId = new ArrayList<String>();
setLatestPricesResults(request.findLatestPrices());
for (Iterator<OrderBook> it = orderBookResults.iterator(); it.hasNext();)
{
OrderBook orderBook = it.next();
logger.log(Level.INFO, "Found {0} orderbook price", orderBook.getPrice());
}
logger.log(Level.INFO, "End of findLatestPrices with user {0} ",user.getUserId());
}
这调用了我的 RequestScoped Stateful ejb:
public List<OrderBook> findLatestPrices() {
List<OrderBook> orderBooks;
List<OrderBook> orderBooksFiltered;
Map<Member, OrderBook> map = new LinkedHashMap<Member, OrderBook>();
try {
orderBooks = em.createNamedQuery(
"findAllOrderBooks").setHint("javax.persistence.cache.storeMode", "REFRESH")
.getResultList();
for (Iterator<OrderBook> it = orderBooks.iterator(); it.hasNext();) {
OrderBook orderBook = it.next();
Member member = orderBook.getBidOrderId().getMember();
map.put(member, orderBook);
logger.log(Level.INFO, "findLatestPrices orderbook price : {0}",
orderBook.getPrice());
logger.log(Level.INFO, "findLatestPrices orderbook bidorder member : {0}",
orderBook.getBidOrderId().getMember().getMemberId());
logger.log(Level.INFO, "findLatestPrices orderbook lastupdate : {0}",
orderBook.getLastUpdate());
}
...}
我在上面的bean中创建EntityManager的方式如下:
@PersistenceContext
private EntityManager em;
从日志记录中我可以看到会话返回的数据与数据库不同步,即当我期望两个结果时会返回单个结果等。如您所见,我已尝试使用 setHint 刷新缓存。我还在我的 OrderBook 实体和 @Cache(refreshAlways=true) 上尝试了 @Cacheable(false) 但无济于事。
我正在创建的实体 (OrderBook) 的 @PostPersist 中发送推送事件。我的 xhtml 页面中的 javascript 事件处理程序然后调用以下远程命令:
<p:remoteCommand name="updateWidget"
autoRun="false"
actionListener="#{parliamentManager.findLatestPrices}"
update="resultDisplay"
onstart="onStart()"
oncomplete="onComplete()"
onsuccess="onSuccess()"
onerror="onError()">
<f:actionListener binding="#{parliamentManager.findTraders()}" />
<f:actionListener binding="# {parliamentManager.findPortfolios()}" />
</p:remoteCommand>
findLatestPrices 的结果似乎通常不包括所有会话的最新 OrderBook 实体。是否有可能实体在调用@PostPersist 时没有立即持久化,研究理论是在实体完全持久化并由JPA 反映之前将推送发送到某些会话?
为了演示,我添加了一个简单的命令按钮来手动调用 updateWidget()。如果会话未更新并且我单击按钮,它总是会更新为最新数据。
谢谢, 佐博
【问题讨论】:
-
在查询
em.getEntityManagerFactory().getCache().evictAll()之前有没有尝试清除缓存 -
感谢 simdevmon 的回复。我试过了,但不幸的是它没有任何区别。
标签: jpa jakarta-ee eclipselink