【发布时间】:2013-03-21 15:41:54
【问题描述】:
我目前正在开发一些由 SAP 系统触发的 Java 网络服务(以及带有 MySQL 连接的 JPA)。
为了简化我的问题,我将两个关键实体称为BlogEntry 和Comment。一个BlogEntry 可以有多个Comments。 Comment 始终只属于一个 BlogEntry。
所以我有三个服务(我不能也不想重新定义它们,因为它们是由我从 SAP 导出并使用并行与其他系统通信的 WSDL 定义的):CreateBlogEntry、@987654328 @,CreateCommentForUpcomingBlogEntry
它们被正确触发,CreateBlogEntry 或 CreateComment 在单独调用时绝对没有问题。
但是:服务CreateCommentForUpcomingBlogEntry 发送Comment 和一个“外键”来识别“即将到来的”BlogEntry。在内部,它还调用CreateBlogEntry 来创建实际的BlogEntry。 由于它们的异步特性,这两个服务是并发的。
所以我有两个选择:
- 创建一个虚拟
BlogEntry并将Comment连接到它并更新BlogEntry,一旦CreateBlogEntry“到达” - 等待
CreateBlogEntry,然后将Comment连接到新的BlogEntry
目前我正在尝试前者,但是一旦两个服务都完全执行,我最终会得到两个 BlogEntries。其中一个只有CreateCommentForUpcomingBlogEntry 提供的ID,但它已正确连接到Comment(反之亦然)。另一个BlogEntry 拥有所有其他信息(例如postDate 或body),但Comment 没有与之关联。
这里是服务实现CreateCommentForUpcomingBlogEntry的代码sn-p:
@EJB
private BlogEntryFacade blogEntryFacade;
@EJB
private CommentFacade commentFacade;
...
List<BlogEntry> blogEntries = blogEntryFacade.findById(request.getComment().getBlogEntryId().getValue());
BlogEntry persistBlogEntry;
if (blogEntries.isEmpty()) {
persistBlogEntry = new BlogEntry();
persistBlogEntry.setId(request.getComment().getBlogEntryId().getValue());
blogEntryFacade.create(persistBlogEntry);
} else {
persistBlogEntry = blogEntries.get(0);
}
Comment persistComment = new Comment();
persistComment.setId(request.getComment().getID().getValue());
persistComment.setBody(request.getComment().getBody().getValue());
/*
set other properties
*/
persistComment.setBlogEntry(persistBlogEntry);
commentFacade.create(persistComment);
...
这是实现CreateBlogEntry的代码sn-p:
@EJB
private BlogEntryFacade blogEntryFacade;
...
List<BlogEntry> blogEntries = blogEntryFacade.findById(request.getBlogEntry().getId().getValue());
BlogEntry persistBlogEntry;
Boolean update = false;
if (blogEntries.isEmpty()) {
persistBlogEntry = new BlogEntry();
} else {
persistBlogEntry = blogEntries.get(0);
update = true;
}
persistBlogEntry.setId(request.getBlogEntry().getId().getValue());
persistBlogEntry.setBody(request.getBlogEntry().getBody().getValue());
/*
set other properties
*/
if (update) {
blogEntryFacade.edit(persistBlogEntry);
} else {
blogEntryFacade.create(persistBlogEntry);
}
...
这是一些无法使事情按预期发生的摆弄。
遗憾的是,我还没有找到同步这些同时服务调用的方法。我可以让CreateCommentForUpcomingBlogEntry sleep 几秒钟,但我认为这不是正确的做法。
我可以强制我的facades 和它们各自的EntityManagers 的每个实例重新加载它们的数据集吗?我可以将我的请求放入某种队列中,该队列会根据某些条件被清空吗?
那么:让它等待BlogEntry 存在的最佳做法是什么?
提前致谢, 大卫
信息:
- GlassFish 服务器 3.1.2
- EclipseLink,版本:Eclipse Persistence Services - 2.3.2.v20111125-r10461
【问题讨论】:
-
如果已经存在具有相同 id(由
CreateCommentForUpcomingBlogEntry创建)的博客条目,您为什么不签入CreateBlogEntry?如果是,更新而不是创建。 -
这正是我目前正在尝试做的(参见第二个代码 sn-p)。
-
过失。奇怪的是你得到两个条目(具有相同的唯一 ID?)
-
我可能不得不说,ID 是指由发布 SAP 系统生成的值,并不是真正的 ID,数据库有自己的一组主键(真正的唯一 ID)。现在,我通过在我的
facade中调用getEntityManager().getEntityManagerFactory().getCache().evictAll();告诉CreateCommentForUpcomingBlogEntry-Thread 休眠10 秒并清除EntityManger 的缓存,设法使我的代码正常运行。我仍然拒绝相信这是最好的解决方案:( -
换句话说
blogEntryFacade.edit(persistBlogEntry);fails 更新当前记录bu创建一个新记录?听起来很牛逼。你确定你的持久化策略没问题吗?
标签: java web-services jpa persistence