【发布时间】:2010-11-25 13:59:05
【问题描述】:
我用以下代码编写了一个 grails 服务:
EPCGenerationMetadata requestEPCs(String indicatorDigit, FilterValue filterValue,
PartitionValue partitionValue, String companyPrefix, String itemReference,
Long quantity) throws IllegalArgumentException, IllegalStateException {
//... code
//problematic snippet bellow
def serialGenerator
synchronized(this) {
log.debug "Generating epcs..."
serialGenerator = SerialGenerator.findByItemReference(itemReference)
if(!serialGenerator) {
serialGenerator = new SerialGenerator(itemReference: itemReference, serialNumber: 0l)
}
startingPoint = serialGenerator.serialNumber + 1
serialGenerator.serialNumber += quantity
serialGenerator.save(flush: true)
}
//code continues...
}
作为一个 grails 服务,默认情况下是单例,我认为通过添加上面的同步块可以避免并发不一致。我创建了一个简单的客户端来测试并发性,因为服务是由 http 调用程序公开的。我同时运行多个客户端,将相同的 itemReference 作为参数传递,并且完全没有问题。
但是,当我将数据库从 MySQL 更改为 PostgreSQL 8.4 时,我无法再处理并发访问了。运行单个客户端时,一切都很好。但是,如果我再添加一个请求相同 itemReference 的客户端,我会立即收到 StaleObjectStateException:
线程“主”org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException 中的异常:标识符为 [10] 的类 [br.com.app.epcserver.SerialGenerator] 的对象:乐观锁定失败;嵌套异常是 org.hibernate.StaleObjectStateException:行已被另一个事务更新或删除(或未保存值映射不正确):[br.com.app.epcserver.SerialGenerator#10] 在 org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672) 在 org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412) 在 org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411) 在 org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374) 在 org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:881) 在 org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod$1.doInHibernate(SavePersistentMethod.java:58) (...) 在 br.com.app.EPCGeneratorService.requestEPCs(EPCGeneratorService.groovy:63) 在 br.com.app.epcclient.IEPCGenerator$requestEPCs.callCurrent(未知来源) 在 br.com.app.epcserver.EPCGeneratorService.requestEPCs(EPCGeneratorService.groovy:29) 在 br.com.app.epcserver.EPCGeneratorService$$FastClassByCGLIB$$15a2adc2.invoke() (...) 原因:org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或未保存的值映射不正确):[br.com.app.epcserver.SerialGenerator#10]注意:EPCGeneratorService.groovy:63 指的是serialGenerator.save(flush: true)。
我不知道该怎么想,因为我唯一改变的是数据库。我将不胜感激有关此事的任何建议。
我正在使用:
Grails 1.3.3
Postgres 8.4(postgresql-8.4-702.jdbc4 驱动程序)
JBoss 6.0.0-M4
MySQL:
mysqld Ver 5.1.41 (mysql-connector-java-5.1.13-bin 驱动)
提前致谢!
【问题讨论】:
标签: mysql hibernate spring postgresql grails