开发者

org.hibernate.StaleObjectStateException when using Grails with PostgreSQL

I've written a grails service with the following code:

EPCGenerationMetadata requestEPCs(String indicatorDigit, FilterValue filterValue,     
    PartitionValue partitionValue, String companyPrefix, String itemReference, 
    Long quantity) throws Ill开发者_StackOverflow中文版egalArgumentException, 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...
}

Being a grails service a singleton by default, I thought I'd be safe from concurrent inconsistency by adding the synchronized block above. I've created a simple client for testing concurrency, as the service is exposed by http invoker. I ran multiple clients at the same time, passing as argument the same itemReference, and had no problems at all.

However, when I changed the database from MySQL to PostgreSQL 8.4, I couldn't handle concurrent access anymore. When running a single client, everything is fine. However, if I add one more client asking for the same itemReference, I get instantly a StaleObjectStateException:

Exception in thread "main" org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [br.com.app.epcserver.SerialGenerator] with identifier [10]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [br.com.app.epcserver.SerialGenerator#10]  
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672)  
    at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)  
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)  
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)  
    at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:881)  
    at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod$1.doInHibernate(SavePersistentMethod.java:58)  
    (...)  
    at br.com.app.EPCGeneratorService.requestEPCs(EPCGeneratorService.groovy:63)  
    at br.com.app.epcclient.IEPCGenerator$requestEPCs.callCurrent(Unknown Source)  
    at br.com.app.epcserver.EPCGeneratorService.requestEPCs(EPCGeneratorService.groovy:29)  
    at br.com.app.epcserver.EPCGeneratorService$$FastClassByCGLIB$$15a2adc2.invoke()  
        (...)  
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [br.com.app.epcserver.SerialGenerator#10]

Note: EPCGeneratorService.groovy:63 refers to serialGenerator.save(flush: true).

I don't know what to think, as the only thing that I've changed was the database. I'd appreciate any advice on the matter.

I'm using:

Grails 1.3.3

Postgres 8.4 (postgresql-8.4-702.jdbc4 driver)

JBoss 6.0.0-M4

MySQL:

mysqld Ver 5.1.41 (mysql-connector-java-5.1.13-bin driver)

Thanks in advance!


That's weird, try disabling transaction.


This is indeed a strange behavior, but you could try to workaround by using a "select ... for upgrade", via hibernate lock method.

Something like this:

def c = SerialGenerator.createCriteria()
serialgenerator = c.get {
  eg "itemReferece", itemReference
  lock true
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜