grails / gorm-hibernate5

GORM for Hibernate 5
Apache License 2.0
66 stars 71 forks source link

ValidationException not thrown when Domain has embedded object #110

Open aulea opened 5 years ago

aulea commented 5 years ago

Given the following Domain class

class A {
    String a
    E efs

    static embedded = [ 'efs' ]

    static constraints = {
          a validator: { String newValue, A obj ->
                return ['not.valid.a']
          }
    }
}

and Embedded class

class E {
    String f
}

Steps to Reproduce

When trying to save new instance of domain A with validation error, it fails instead with IllegalArgumentException from Hibernate telling that embedded class E is not an entity. Of course that's true, but i would expect to get original ValidationException.

Originally posted under grails-data-mapping (1199)

The Stacktrace:

java.lang.IllegalArgumentException: Not an entity [class ...]
    at org.hibernate.internal.SessionImpl.contains(SessionImpl.java:2068)
    at org.grails.orm.hibernate.cfg.GrailsHibernateUtil.canModifyReadWriteState(GrailsHibernateUtil.java:316)
    at org.grails.orm.hibernate.cfg.GrailsHibernateUtil.setObjectToReadyOnly(GrailsHibernateUtil.java:305)
    at org.grails.orm.hibernate.HibernateGormInstanceApi.setObjectToReadOnly(HibernateGormInstanceApi.groovy:159)
    at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.handleValidationError(AbstractHibernateGormInstanceApi.groovy:397)
    at org.grails.orm.hibernate.AbstractHibernateGormInstanceApi.save(AbstractHibernateGormInstanceApi.groovy:132)
    at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:151)

The reason is, that gorm tries to set objects with failure to read-only state in hibernate session, but doesn't distinct correctly Embedded objects: AbstractHibernateGormInstanceApi#handleValidationError It loops over all domain's associations and check their instance type ToOne, it should exclude instance type Embedded.

Expected Behaviour

Should fail with ValidationException for validated field

Actual Behaviour

Fails with IllegalArgumentException from Hibernate: Not an Entity [class E]

Environment Information

Workaround is to use manual validation before save and throw by youself new ValidationException created from validated domain errors.

A a = new A()
a.a = 'string'
a.efs = new E(f: 'string')

if (!a.validate()) {
      throw new ValidationException("Validation Error(s) occurred during save()", a.errors)
}
a.save(flush: true)
longwa commented 4 years ago

Can this be considered for inclusion in a release?

We are running a custom build with the fix attached with no problems for some time. It would be nice if we could stop having to build this fix ourselves.

billgonemad commented 3 years ago

I am seeing similar behavior with Grails 4.0.3/GORM 7.0.4.RELEASE where I am getting the not an entity exception being thrown on an embedded object.

billgonemad commented 3 years ago

I've issued PR #378 to address this based on the 7.0.x branch.

naruto0426 commented 2 years ago

@longwa Can you help to build a new tag released include this patch. Without this patch, the error for save failed will be wrong when it has embedded column that is not declared as entity.