无法在Grails 2.4.5

时间:2015-07-13 20:27:31

标签: hibernate grails asynchronous groovy

我一直试图找出为什么我无法解决这个问题无济于事。

基本上,我有一个域类(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

正如您所看到的,即使已处理的标志已标记为true,第二个请求仍以某种方式找到了PrizeSchedule实例。

我尝试过这个查询的变体来找到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'

这是因为这些领域中使用的通用接口和抽象类。

我希望有人可以提供帮助,并提前感谢您花时间阅读本文!

2 个答案:

答案 0 :(得分:1)

好的我发布这个作为我的问题的解决方案,以防万一其他人在将来遇到这个问题。这可能是显而易见的,但作为Grails的相对新人,我发现这很难解决/找到有关的信息。

基本上我的控制器是用

注释的
@Transactional(readOnly = true)

进行实际处理的方法用

注释
@Transactional

最后,服务本身也注明了

@Transactional

我的假设是,这些注释会以某种方式混合在Hibernate会话中访问和存储数据时使用的事务。从控制器中删除注释(并调整代码)并将我的服务作为@Transactional组件后 - 一切都按照我的预期开始工作。

我希望这可以帮助像我一样受苦的人!

答案 1 :(得分:0)

我希望您理解,当您使用乐观锁进行并发更新时,可能会抛出StateObjectStateException。随着模型中并发性的增加,它将变得更加普遍。

由于您提到这是预定作业的一部分,您可以使用代码在新会话中重试奖励,例如,安排另一个作业立即再次运行。