This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit a4617c9106ffbd108e5f75d3507722c8046c190f Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Mar 7 19:34:41 2026 -0600 hibernate7: HibernateGormValidationApi bug fix --- .../hibernate/HibernateGormValidationApi.groovy | 14 ++- .../HibernateGormValidationApiSpec.groovy | 121 +++++++++++++++++++++ 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy index 2bf204e982..666ab92cba 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy @@ -57,7 +57,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> { Validator validator = getValidator() if (validator == null) return true - Boolean valid = Boolean.TRUE + boolean valid = true boolean evict = false boolean deepValidate = true Set validatedFields = null @@ -69,7 +69,9 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> { deepValidate = ClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments) } - evict = ClassUtils.getBooleanFromMap(ARGUMENT_EVICT, arguments) + if (arguments?.containsKey(ARGUMENT_EVICT)) { + evict = ClassUtils.getBooleanFromMap(ARGUMENT_EVICT, arguments) + } fireEvent(instance, validatedFieldsList) @@ -95,7 +97,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> { errors = filterErrors(errors, validatedFields, instance) if (errors.hasErrors()) { - valid = Boolean.FALSE + valid = false if (evict) { if (hibernateTemplate.contains(instance)) { hibernateTemplate.evict(instance) @@ -116,8 +118,8 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> { datastore.getApplicationEventPublisher().publishEvent(event) } - @SuppressWarnings("rawtypes") - private Errors filterErrors(Errors errors, Set validatedFields, Object target) { + @SuppressWarnings('rawtypes') + private static Errors filterErrors(Errors errors, Set validatedFields, Object target) { if (validatedFields == null) return errors ValidationErrors result = new ValidationErrors(target) @@ -135,7 +137,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> { return result } - protected Errors setupErrorsProperty(Object target) { + protected static Errors setupErrorsProperty(Object target) { HibernateRuntimeUtils.setupErrorsProperty target } } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy new file mode 100644 index 0000000000..f5be2b07ce --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.grails.orm.hibernate + +import grails.gorm.annotation.Entity +import grails.gorm.transactions.Rollback +import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.orm.hibernate.cfg.Settings +import org.springframework.core.env.PropertyResolver +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification + +class HibernateGormValidationApiSpec extends Specification { + + @Shared PropertyResolver configuration = DatastoreUtils.createPropertyResolver( + (Settings.SETTING_DB_CREATE): 'create-drop', + 'dataSource.url': 'jdbc:h2:mem:validationApiSpec;LOCK_TIMEOUT=10000' + ) + @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(configuration, ValidatedBook) + @Shared PlatformTransactionManager transactionManager = hibernateDatastore.getTransactionManager() + + @Rollback + void "validate returns true (not a boxed Boolean) for a valid instance"() { + given: + def book = new ValidatedBook(title: 'Clean Code') + + when: + def result = book.validate() + + then: + result == true + result instanceof Boolean + !book.hasErrors() + } + + @Rollback + void "validate returns false for an invalid instance"() { + given: + def book = new ValidatedBook(title: null) + + when: + def result = book.validate() + + then: + result == false + book.hasErrors() + book.errors.getFieldError('title') + } + + @Rollback + void "validate with evict:false (default) leaves invalid instance in the session"() { + given: + def book = new ValidatedBook(title: 'Valid Title').save(flush: true) + book.title = null + def session = hibernateDatastore.sessionFactory.currentSession + + when: + def result = book.validate(evict: false) + + then: + result == false + session.contains(book) + } + + @Rollback + void "validate with evict:true removes invalid instance from the session"() { + given: + def book = new ValidatedBook(title: 'Valid Title').save(flush: true) + book.title = null + def session = hibernateDatastore.sessionFactory.currentSession + + when: + def result = book.validate(evict: true) + + then: + result == false + !session.contains(book) + } + + @Rollback + void "validate with specific fields only validates those fields"() { + given: + def book = new ValidatedBook(title: null, author: null) + + when: + def result = book.validate(['author']) + + then: + result == true + !book.hasErrors() + } +} + +@Entity +class ValidatedBook { + String title + String author + + static constraints = { + title nullable: false + author nullable: true + } +}
