【发布时间】:2015-07-13 20:27:31
【问题描述】:
我已经尝试了好几个小时来弄清楚为什么我无法解决这个问题。
基本上,我有一个域类 (PrizeSchedule),它在我的应用程序中用于安排何时发放奖品。当收到请求并且是发放奖品的时间(计划时间比现在短)时,它将分配该奖品并将其标记为已处理。
这意味着,如果参赛作品之间有足够的时间间隔,则可能有 2 个或更多奖品可供赠送。当我直接使用 10 个(或更多)请求测试我的应用程序时,在这种情况下,我总是在一些请求上遇到以下问题:
optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
我尝试过使用prizeScheduleInstance.merge 和prizeScheduleInstance.lock,但弹出相同的错误。很长一段时间后,我发现 PrizeSchedule.find() 调用没有产生正确的结果。尽管之前的请求完成了以下操作,但似乎:
prizeSchedule.setProcessed(true);
prizeSchedule.setReferenceNumber(prizeSchedule.generateToken());
prizeSchedule.save(flush:true);
下一个请求仍然能够找到处理后的 PrizeSchedule 实例,您可以在下面的日志中看到这里
请求 1:
2015-07-13 22:05:28,915 [http-bio-8080-exec-7] DEBUG PrizeService - Session ID: 603 won prize ID: 103314
请求 2:
2015-07-13 22:05:30,136 [http-bio-8080-exec-12] DEBUG PrizeService - Session ID: 604 won prize ID: 103314
如您所见,第二个请求仍然以某种方式找到了 PrizeSchedule 实例,即使已处理标志已被标记为 true。
我尝试了这个查询的变体来查找 PrizeSchedule 实例,它们都产生相同的问题,下面是我尝试过的问题
PrizeSchedule ps = PrizeSchedule.findByCampaignAndDateScheduledLessThanAndProcessed(campaign, new Date(), false, [cache: false])
和
PrizeSchedule ps = ps = PrizeSchedule.find("FROM PrizeSchedule ps WHERE ps.campaign = :campaign AND ps.processed = :processed AND ps.dateScheduled < :now ORDER BY ps.dateScheduled ASC",
[campaign: campaign, processed: false, now: new Date()], [cache: false]
)
如果它很重要 - 我有调用服务来处理请求的控制器,这反过来又调用其他 groovy/src 代码,这些代码通过使用 PrizeService
def prizeService = Holders.grailsApplication.mainContext.getBean 'prizeService'
这是因为在这些领域中使用了通用接口和抽象类。
希望有人能提供帮助,提前感谢您抽出宝贵时间阅读本文!
【问题讨论】:
-
无需挖掘比您发布的更多代码,您应该非常关注的第一件事是使用
Holders进行DI。这是一个巨大的危险信号,表明您的设计存在根本缺陷。使用Holders应该与正在创建的宇宙一样罕见。我不是在开玩笑。 -
老实说,我这样做是出于绝望 - 我直接在 groovy/src 中使用对象,我认为这可能与那些不遵守 @Transactional 方法注释的人有关(不是完全理解 Hibernate)——同样的问题发生在不使用 Holders 并直接在 groovy/src 中进行分配的情况下。感谢您指出这一点 - 我将重新调整代码,使其恢复原状。
-
@JoshuaMoore 我已将其改回为直接从 groovy/src 块运行代码 - 相同的行为:(
标签: hibernate grails asynchronous groovy