Search code examples
hibernategrailsgrails-orm

How to update duplicate records in grails


We are allowing duplicate records in the database with the exception of id. When a record is updated, we want to find and update any duplicates. Through research I have found Hibernate's event method beforeUpdate and afterUpdate. The problem is that when I find duplicates and start iterating through them, I get this error:

ERROR:Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

Here is my afterUpdate code in the Domain:

1      def afterUpdate() {
2          println "\n*** afterUpdate ***"
3          def record = this
4
5          DomainObject.createCriteria().list() {
6              ne( 'id', record.id )
7              or {
8                  eq( 'storeId', record.storeId )
9                  and {
10                     eq( 'firstName', record.firstName )
11                     eq( 'lastName', record.lastName )
12                     eq( 'dateOfBirth', record.dateOfBirth )
13                 }
14             }
15             //eq( 'lastUpdated', record.lastUpdated )
16         }.each { dupe ->
17             log.info "syncing ${dupe.id} with ${record.id}"
18             dupe.properties.each{ key, value ->
19                 println "*** prop: ${key}: ${value}"
20             }
21         }
22     }
23

The error is on line 19. We are using Grails 2.4.4 and developing on Windows


Solution

  • Take a look at the documentation. Pay attention to this section about the use of withNewSession:

    class Person {
       String name
       def beforeDelete() {
          ActivityTrace.withNewSession {
             new ActivityTrace(eventName: "Person Deleted", data: name).save()
          }
       }
    }
    

    Notice the usage of withNewSession method above. Since events are triggered whilst Hibernate is flushing using persistence methods like save() and delete() won't result in objects being saved unless you run your operations with a new Session.

    Fortunately the withNewSession method lets you share the same transactional JDBC connection even though you're using a different underlying Session.