Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

automatic dirty checking not working on array type #106

Open
nicsl0s opened this issue Jun 7, 2017 · 6 comments
Open

automatic dirty checking not working on array type #106

nicsl0s opened this issue Jun 7, 2017 · 6 comments

Comments

@nicsl0s
Copy link

nicsl0s commented Jun 7, 2017

In a grails app I have a domain class like this:

class User {
         String[] privileges = ['JUNIOR_BIZDEV','TECHNICAL_ADMIN']
 
         Set<String> getPrivilegesSet() {
                return privileges.collect {it } as Set<String>
         }

        // convenience method to modify the user privileges
        void addToPrivilegesSet(String privilege) {
               def tmp = privilegesSet
               tmp.add(privilege)
               privileges = tmp.collect { it } as String[]
        }
}

// calling user somewhere
def user = User.get(SOME_ID)
user.addToRoleSet('JUNIOR_SOMETHING_ADMIN') // this causes the privileges to be dirty and the user got saved with a further role
user.save()

This used to work when using:
org.grails.plugins:postgresql-extensions:4.6.2
grails version 3.2.8
gorm version 6.0.9.RELEASE

This stopped working when using:
grails version 3.2.9
gorm version 6.1.4.RELEASE

I think the reason is some change in the new gorm version. It stops working since version gorm 6.1.0
Also using the org.grails.plugins:postgresql-extensions:5.1.0 did not change it.
The workaround was to add a markDirty() in the convenience method:

  void addToPrivilegesSet(String privilege) {
               def tmp = privilegesSet
               tmp.add(privilege)
               privileges = tmp.collect { it } as String[]
               markDirty('privileges')
        }

Any Hints?
Thx

@jglapa
Copy link
Contributor

jglapa commented Jun 7, 2017

Don't have an answer but I recently discovered and fixed a similar dirty checking issue with hstore type in this plugin.
Perhaps you could read my explanation notes and debug it the same way? -> #104 (comment)

It might give you some hints where the dirty checking mechanism fails.
Looking at the definition of ArrayType here and the deepCopy method implementation https://github.com/kaleidos/grails-postgresql-extensions/blob/master/src/main/groovy/net/kaleidos/hibernate/usertype/ArrayType.java#L70

I would say that if something changed in Hibernate that it now compares by reference and not value the indeed this would explain your problem.
And your fix of course helps because you are creating a completely new array.

@ilopmar
Copy link
Collaborator

ilopmar commented Jun 19, 2017

Hi.

Dirty-checking has changed and been improved on Gorm 6.1. You can see an explanation by Graeme on how it works here: grails/grails-data-mapping#961

@igorrosenberg
Copy link

I have observed the same missing drty-checking on Map types (JSON). As a temporary work-around, I forcibly modify another field of the Domain instance to make sure the save is performed :

domain.mapField.a  = 1 // some appended/updated data in domain.mapField
domain.dateCreated = new Date(domain.dateCreated.time+1) // dateCreated modification is an ugly workaround to the dirty-checking failure  
domain.save()

@mhuebner
Copy link

mhuebner commented Aug 1, 2017

I also encountered this issue. Setting a Map property via setter internally calls markDirty but when using leftShift operator to add add some stuff to the map this would not work.

def additionalMapData = ['foo':'baar']
persistedInstance.mapProperty << additionalMapData 

@animator013
Copy link

animator013 commented Aug 7, 2017

Have also the same problem with Gorm 6.1.x. Also with Map type.

@mhuebner
Copy link

mhuebner commented Aug 7, 2017

If you want a collection to be dirty checked you will have to call the setter or manually set markDirty() on the instance. I am using the first variant so I have not too much framework-specific code within my classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants