我在JPA中持久保存新对象,然后想要异步索引它。因此,我创建对象,持久化,刷新EntityManager,获取新的id,然后调用异步方法以使索引运行。唉 - 异步方法无法从数据库中检索对象。
存储代码:
em().persist(theDataset);
// updates....
theDataset = ctxt.em().merge(theDataset); // store last updates
ctxt.em().flush();
logger.info( "New dataset id is: " + theDataset.getId() ); // logs a valid id
indexSvc.asyncIndexDataset(theDataset.getId(), true)
检索代码:
@Asynchronous
public Future<String> asyncIndexDataset(long datasetId, boolean doNormalSolrDocCleanUp) {
Dataset toIndex = em.find(Dataset.class, datasetId);
if ( toIndex == null ) {
logger.log(Level.WARNING, "Cannot find dataset with id {0}", datasetId);
return new AsyncResult<>(null);
} else {
return indexDataset(toIndex, doNormalSolrDocCleanUp);
}
}
结果日志:
[2018-04-10T17:41:39.275+0300] [glassfish 4.1] [INFO] [] [...] [tid: _ThreadID=30 _ThreadName=http-listener-1(4)] [timeMillis: 1523371299275] [levelValue: 800] [[
New dataset id is: 20]]
[2018-04-10T17:41:39.305+0300] [glassfish 4.1] [WARNING] [] [...] [tid: _ThreadID=175 _ThreadName=__ejb-thread-pool10] [timeMillis: 1523371299305] [levelValue: 900] [[
Cannot find dataset with id 20]]
我做错了什么?
THX
答案 0 :(得分:1)
刷新实体管理器是不够的。这意味着实体管理器中记录的所有更改都将发送到数据库。 尽管如此,并不意味着其他读者可以阅读这些变化。这取决于数据库的隔离级别。
我认为你的问题是,读者(另一个线程中的索引服务)会去DB读取新持久化的实体,但是原始事务(你持有实体)还没有完成,因此读者找不到它。
我说先让我们完成你的交易,然后尝试对其进行索引,如果只是简单地将持久化对象传递给索引服务,那就更好了(考虑到不会发生任何变化)数据库方面的实体)。