We have recently upgraded to Grails 6.2.3 from 5.2 etting exception when new user is being added to our application and following is the stack trace for the same.
Caused by: .springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session : [***.Person#101211]; nested exception is .hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [**.**.**.Person#101211]
at .springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:230)
at .grails.orm.hibernate.GrailsHibernateTemplate.convertHibernateAccessException(GrailsHibernateTemplate.java:717)
at .grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:301)
at .grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:241)
at .grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:120)
at .grails.orm.hibernate.AbstractHibernateGormInstanceApi.performSave(AbstractHibernateGormInstanceApi.groovy:247)
at .grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:164)
at .grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:153)
at **.**.**.ProdUserService.$tt__createUser(ProdUserService.groovy:72)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
at .springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
at **.**.**.UserController.save(UserController.groovy:158)
Following is the code snippet
Controller class:
def save(){
def userData = new JsonSlurper().parseText(params.userData)
//business logic, some validations
//call to produserservice
CreateUserDTO createUserDTO = prodUserService.createUser(userData, user)
//business logic
Service class:
CreateUserDTO createUser(Map params, ProdUser user) {
ProdUser userInst = new ProdUser()
grailsWebDataBinder.bind userInst, new SimpleMapDataBindingSource(params)
Person person = userInst.person
//business logic - assigning values to person like person.prop1 = userInst.prop1
person.save(failOnError: true) //getting error here!
userInst.save(flush: true, failOnError: true)
new CreateUserDTO(prodUser: userInst, prodUserStatus: prodUserStatus)
Getting error on person.save()
Things to note:
Person and ProdUser are domain classes having parent-child relationship i.e. person BelongsTo ProdUser
There are no code changes around this. This stopped working post upgrade to grails6.
Do I need to update any specific configuration or modify any implementation? Is there any specific order in which save() should be called in case of belongTo relationship.
I tried using merge(), clearing the session but didn't solve the issue.