Grails
  1. Grails
  2. GRAILS-8937

Hibernate StaleObjectStateException thrown when a versioned invalid domain object is in session during a flush

    Details

    • Testcase included:
      yes

      Description

      When an invalid versioned domain object is in the session during a flush (explicit or implicit) the version number is bumped but it is not persisted to the database. Then, when it becomes valid again and saved and flushed, hibernate considers it stale, since the version number does not match the version in the database and it throws a StaleObjectStateException.

      Example from attached test case:

          void "test invalid versioned object in session"() {
              def foo = new Foo(name:'valid')
              foo.save(failOnError:true, flush:true)
      
              def bar = new Bar(name:'valid')
              bar.save(failOnError:true, flush:true)
              
              assert foo.version == 0
              
              bar.name = 'valid2'
              foo.name = 'invalid'
              bar.save(failOnError:true, flush:true)
      
              assert foo.version == 1
              
              foo.name = 'valid2'
              
              //fails here
              foo.save(failOnError:true, flush:true)
          }
      

      This is synthetic, but it happens in more complicated normal production code without explicit flushes.

        Activity

        Hide
        Graeme Rocher added a comment -

        Unfortunately this cannot be fixed and appears like a bug in Hibernate and will need a JIRA will need to be raised against Hibernate.

        I have committed a test

        https://github.com/grails/grails-core/commit/983d6676c469fc2335f9cfa4c9d47504b2789883

        The workaround is discard the update by calling foo.discard() and re-apply the changes

        Show
        Graeme Rocher added a comment - Unfortunately this cannot be fixed and appears like a bug in Hibernate and will need a JIRA will need to be raised against Hibernate. I have committed a test https://github.com/grails/grails-core/commit/983d6676c469fc2335f9cfa4c9d47504b2789883 The workaround is discard the update by calling foo.discard() and re-apply the changes
        Hide
        Graeme Rocher added a comment -

        Note it may be the expected Hibernate behavior to increment the version regardless of the operation, although I don't see how

        Show
        Graeme Rocher added a comment - Note it may be the expected Hibernate behavior to increment the version regardless of the operation, although I don't see how

          People

          • Assignee:
            Graeme Rocher
            Reporter:
            Michael Cameron
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development