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 217121b3c413dbddfbe49867cda3dcb9c4109daa Author: Walter Duque de Estrada <[email protected]> AuthorDate: Thu Mar 5 16:05:27 2026 -0600 hibernate7: CloseSuppressingInvocationHandler --- grails-data-hibernate7/core/COVERAGE.md | 255 +++++++++++++++++++++ .../CloseSuppressingInvocationHandler.java | 79 +++++++ .../CloseSuppressingInvocationHandlerSpec.groovy | 93 ++++++++ 3 files changed, 427 insertions(+) diff --git a/grails-data-hibernate7/core/COVERAGE.md b/grails-data-hibernate7/core/COVERAGE.md new file mode 100644 index 0000000000..b69ba9a97e --- /dev/null +++ b/grails-data-hibernate7/core/COVERAGE.md @@ -0,0 +1,255 @@ +# Hibernate 7 Core Module Test Coverage + +| Class | Instruction Coverage | +| :--- | :--- | +| org.grails.orm.hibernate.GrailsHibernateTemplate.CloseSuppressingInvocationHandler | 0% | +| org.grails.orm.hibernate.HibernateDatastore.new DataSourceConnectionSourceFactory() {...} | 0% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._delete_closure2 | 0% | +| org.grails.orm.hibernate.HibernateGormStaticApi._get_closure1 | 0% | +| org.grails.orm.hibernate.SessionFactoryHolder | 0% | +| org.grails.orm.hibernate.cfg.InstanceProxy | 0% | +| org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy | 0% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedCollectionProperty | 0% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder.new GroovyObject() {...} | 0% | +| org.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException | 0% | +| org.grails.orm.hibernate.exceptions.GrailsHibernateConfigurationException | 0% | +| org.grails.orm.hibernate.exceptions.GrailsHibernateException | 0% | +| org.grails.orm.hibernate.query.HibernateQueryConstants | 0% | +| org.grails.orm.hibernate.support.DataSourceFactoryBean | 0% | +| org.grails.orm.hibernate.support.HibernateDatastoreConnectionSourcesRegistrar | 0% | +| org.grails.orm.hibernate.support.HibernateDatastoreFactoryBean | 0% | +| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean | 0% | +| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean.new DialectResolutionInfoSource() {...} | 0% | +| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean.new ServiceRegistryImplementor() {...} | 0% | +| org.grails.orm.hibernate.cfg.domainbinding.util.GeneratorCreationContextWrapper | 16% | +| org.grails.orm.hibernate.InstanceApiHelper | 17% | +| org.grails.orm.hibernate.GrailsSessionContext | 26% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPassBinder | 32% | +| org.grails.orm.hibernate.cfg.GrailsHibernateUtil | 35% | +| org.grails.orm.hibernate.cfg.Table | 35% | +| org.grails.orm.hibernate.cfg.ColumnConfig | 42% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPassBinder | 43% | +| org.grails.orm.hibernate.exceptions.GrailsQueryException | 44% | +| org.grails.orm.hibernate.query.MutationQueryDelegate | 45% | +| org.grails.orm.hibernate.cfg.Identity | 46% | +| org.grails.orm.hibernate.HibernateDatastore.new HibernateGormEnhancer() {...} | 50% | +| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration | 54% | +| org.grails.orm.hibernate.query.GrailsHibernateQueryUtils | 54% | +| org.grails.orm.hibernate.query.SelectQueryDelegate | 57% | +| org.grails.orm.hibernate.HibernateDatastore | 59% | +| org.grails.orm.hibernate.cfg.SortConfig | 59% | +| org.grails.orm.hibernate.HibernateEventListeners | 60% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedPersistentEntity | 60% | +| org.grails.orm.hibernate.proxy.HibernateProxyHandler | 61% | +| org.grails.orm.hibernate.HibernateSession | 62% | +| org.grails.orm.hibernate.cfg.MappingCacheHolder | 63% | +| org.grails.orm.hibernate.GrailsHibernateTransactionManager | 65% | +| grails.orm.HibernateCriteriaBuilder | 67% | +| org.grails.orm.hibernate.cfg.JoinTable | 67% | +| org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory | 67% | +| org.grails.orm.hibernate.GrailsHibernateTemplate | 68% | +| org.grails.orm.hibernate.access.TraitPropertyAccessStrategy | 69% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsIncrementGenerator | 70% | +| org.grails.orm.hibernate.query.HqlQueryDelegate | 71% | +| org.grails.orm.hibernate.cfg.DiscriminatorConfig | 72% | +| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettingsBuilder | 72% | +| org.grails.orm.hibernate.cfg.IdentityEnumType | 74% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SingleTableSubclassBinder | 74% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsNativeGenerator | 74% | +| org.grails.orm.hibernate.support.SoftKey | 75% | +| org.grails.orm.hibernate.EventListenerIntegrator | 76% | +| org.grails.orm.hibernate.HibernateDatastore.new HibernateDatastore() {...} | 78% | +| org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehaviorFetcher | 78% | +| org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor | 78% | +| org.grails.orm.hibernate.cfg.Mapping | 79% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingFactory | 79% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty | 79% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BasicCollectionElementBinder | 80% | +| org.grails.orm.hibernate.cfg.CompositeIdentity | 81% | +| org.grails.orm.hibernate.multitenancy.MultiTenantEventListener | 81% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionWithJoinTableBinder | 82% | +| org.grails.orm.hibernate.query.GrailsHibernateQueryUtils.new Comparator() {...} | 82% | +| org.grails.orm.hibernate.cfg.domainbinding.util.TableForManyCalculator | 84% | +| org.grails.orm.hibernate.event.listener.HibernateEventListener | 84% | +| org.grails.orm.hibernate.HibernateGormInstanceApi | 85% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateIdentityMapping | 85% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder | 86% | +| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings.HibernateSettings | 86% | +| org.grails.orm.hibernate.query.PredicateGenerator | 86% | +| grails.orm.CriteriaMethodInvoker | 87% | +| org.grails.orm.hibernate.cfg.CacheConfig | 87% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder | 87% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType | 87% | +| org.grails.orm.hibernate.HibernateGormStaticApi | 88% | +| org.grails.orm.hibernate.HibernateGormValidationApi | 88% | +| org.grails.orm.hibernate.cfg.IdentityEnumType.BidiEnumMap | 88% | +| org.grails.orm.hibernate.cfg.domainbinding.util.NamespaceNameExtractor | 88% | +| org.grails.orm.hibernate.query.PagedResultList | 88% | +| org.grails.orm.hibernate.support.HibernateRuntimeUtils | 88% | +| org.grails.orm.hibernate.cfg.PropertyConfig | 89% | +| org.grails.orm.hibernate.cfg.PropertyDefinitionDelegate | 89% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceStyleGenerator | 89% | +| org.grails.orm.hibernate.cfg.domainbinding.util.UniqueKeyForColumnsCreator | 89% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ClassPropertiesBinder | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsTableGenerator | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToOneProperty | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher | 90% | +| org.grails.orm.hibernate.query.HibernateAssociationQuery | 90% | +| org.grails.orm.hibernate.query.HibernateQueryExecutor | 90% | +| org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider | 91% | +| org.grails.orm.hibernate.support.ClosureEventListener | 91% | +| org.grails.orm.hibernate.HibernateGormEnhancer | 92% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder | 92% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.RootPersistentClassCommonValuesBinder | 92% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceGeneratorEnum | 92% | +| org.grails.orm.hibernate.cfg.domainbinding.util.GrailsEnumType | 92% | +| org.grails.orm.hibernate.cfg.domainbinding.util.UniqueNameGenerator | 92% | +| org.grails.orm.hibernate.compiler.HibernateEntityTransformation | 92% | +| org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy | 92% | +| org.grails.orm.hibernate.query.HibernateHqlQuery | 92% | +| org.grails.orm.hibernate.query.HibernateQuery | 92% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._delete_closure1 | 93% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnBinder | 93% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation | 93% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder | 93% | +| org.grails.orm.hibernate.cfg.NaturalId | 94% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder | 94% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity | 94% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyBinder | 94% | +| org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy._findDirty_closure1 | 94% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._performMerge_closure4 | 95% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._performPersist_closure5 | 95% | +| org.grails.orm.hibernate.HibernateGormValidationApi._validate_closure1 | 95% | +| org.grails.orm.hibernate.cfg.Identity._getProperties_closure1 | 95% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder | 95% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder | 95% | +| org.grails.orm.hibernate.compiler.HibernateEntityTransformation.new GroovyObject() {...} | 95% | +| org.grails.orm.hibernate.query.HqlQueryContext | 95% | +| org.grails.orm.hibernate.HibernateGormStaticApi._list_closure7 | 96% | +| org.grails.orm.hibernate.cfg.HibernateMappingContext | 96% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder | 96% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder | 96% | +| org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyWrapper | 96% | +| grails.gorm.hibernate.mapping.MappingBuilder.ClosureMappingDefinition | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleIdBinder | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder._id_closure1 | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionSecondPassBinder | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.util.LogCascadeMapping | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder | 97% | +| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings.HibernateSettings.FlushSettings.FlushMode | 97% | +| org.grails.orm.hibernate.query.HibernateQueryArgument | 97% | +| org.grails.orm.hibernate.query.JpaFromProvider | 97% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.IndexBinder | 98% | +| org.grails.orm.hibernate.query.ProjectionPredicate | 98% | +| grails.orm.CriteriaMethods | 99% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnConfigToColumnBinder | 99% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder | 99% | +| org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder | 99% | +| grails.gorm.hibernate.mapping.MappingBuilder | 100% | +| org.grails.orm.hibernate.HibernateDatastore.new Closure() {...} | 100% | +| org.grails.orm.hibernate.HibernateDatastore.new HibernateDatastore() {...} | 100% | +| org.grails.orm.hibernate.HibernateDatastore.new MappingContext.Listener() {...} | 100% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._attach_closure3 | 100% | +| org.grails.orm.hibernate.HibernateGormInstanceApi._getPersistentValue_closure6 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._findAllWhere_closure4 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._findWhere_closure5 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure10 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure8 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure9 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._get_closure2 | 100% | +| org.grails.orm.hibernate.HibernateGormStaticApi._read_closure3 | 100% | +| org.grails.orm.hibernate.MetadataIntegrator | 100% | +| org.grails.orm.hibernate.SchemaTenantDataSource | 100% | +| org.grails.orm.hibernate.access.TraitPropertyAccessStrategy.new PropertyAccess() {...} | 100% | +| org.grails.orm.hibernate.cfg.CompositeIdentity._getHibernateProperties_closure1 | 100% | +| org.grails.orm.hibernate.cfg.CompositeIdentity._getHibernateProperties_closure2 | 100% | +| org.grails.orm.hibernate.cfg.GrailsNamedStrategyContributor | 100% | +| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.new ClassLoaderServiceImpl() {...} | 100% | +| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.new SessionFactoryObserver() {...} | 100% | +| org.grails.orm.hibernate.cfg.Identity._getProperties_closure1._closure2 | 100% | +| org.grails.orm.hibernate.cfg.PropertyConfig._getTypeName_closure1 | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.DiscriminatorPropertyBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ForeignKeyOneToOneBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.IdentityBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.JoinedSubClassBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneValuesBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.NaturalIdentifierBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.NumericColumnConstraintsBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.PropertyBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.RootBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.StringColumnConstraintsBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SubClassBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.SubclassMappingBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.UnionSubclassBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.binder.VersionBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.BagCollectionType | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.ListCollectionType | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.MapCollectionType | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.SetCollectionType | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.collectionType.SortedSetCollectionType | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsIdentityGenerator | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceGeneratorEnum._fromName_closure1 | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceWrapper | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsJpaMappingConfigurationStrategy | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateBasicProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateClassMapping | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCustomEnumProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCustomProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedClassMapping | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateIdentityProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder._handlePropertyInternal_closure2 | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentEntity | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateSimpleEnumProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateSimpleProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateTenantIdProperty | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalMapElementBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalOneToManyLinker | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyColumnUpdater | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionMultiTenantFilterBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionOrderByBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.DependentKeyValueBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.GrailsSecondPass | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPass | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ManyToManyElementBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPass | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.PrimaryKeyValueCreator | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.SetSecondPass | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyInverseValuesBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.BackticksRemover | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehavior | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.ConfigureDerivedPropertiesConsumer | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.CreateKeyForProps | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.ForeignKeyColumnCountCalculator | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder.SortEntry | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator | 100% | +| org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher | 100% | +| org.grails.orm.hibernate.connections.HibernateConnectionSource | 100% | +| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings | 100% | +| org.grails.orm.hibernate.query.AliasMapEntryFunction | 100% | +| org.grails.orm.hibernate.query.CriteriaAndAlias | 100% | +| org.grails.orm.hibernate.query.DetachedAssociationFunction | 100% | +| org.grails.orm.hibernate.query.GrailsRLikeFunctionContributor | 100% | +| org.grails.orm.hibernate.query.HibernateQuery.new Closure() {...} | 100% | +| org.grails.orm.hibernate.query.JpaCriteriaQueryCreator | 100% | +| org.grails.orm.hibernate.query.PagedResultList.new GrailsHibernateTemplate.HibernateCallback() {...} | 100% | +| org.grails.orm.hibernate.query.RegexDialectPattern | 100% | +| org.hibernate.proxy.HibernateProxyHelper | 100% | diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java new file mode 100644 index 0000000000..b4fa3dc6b3 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java @@ -0,0 +1,79 @@ +/* + * 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 java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +import org.hibernate.Session; +import org.hibernate.query.Query; + +/** + * Invocation handler that suppresses close calls on Hibernate Sessions. Also prepares returned + * Query and Criteria objects. + * + * @see org.hibernate.Session#close + */ +public class CloseSuppressingInvocationHandler implements InvocationHandler { + + protected final Session target; + protected final GrailsHibernateTemplate template; + + public CloseSuppressingInvocationHandler(Session target, GrailsHibernateTemplate template) { + this.target = target; + this.template = template; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Exception { + // Invocation on Session interface coming in... + + switch (method.getName()) { + case "equals" -> { + // Only consider equal when proxies are identical. + return (proxy == args[0]); + // Only consider equal when proxies are identical. + } + case "hashCode" -> { + // Use hashCode of Session proxy. + return System.identityHashCode(proxy); + // Use hashCode of Session proxy. + } + case "close" -> { + // Handle close method: suppress, not valid. + return null; + } + } + + + Object retVal = method.invoke(target, args); + + // If return value is a Query or Criteria, apply transaction timeout. + // Applies to createQuery, getNamedQuery, createCriteria. + if (retVal instanceof org.hibernate.query.Query<?> query) { + template.prepareQuery(query); + } + if (retVal instanceof Query<?> query) { + template.prepareCriteria(query); + } + + return retVal; + + } +} diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy new file mode 100644 index 0000000000..eea98d9883 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy @@ -0,0 +1,93 @@ +/* + * 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 org.hibernate.Session +import org.hibernate.query.Query +import spock.lang.Specification +import java.lang.reflect.Method + +class CloseSuppressingInvocationHandlerSpec extends Specification { + + def "test close is suppressed"() { + given: + Session target = Mock(Session) + GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate) + CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template) + Method closeMethod = Session.class.getMethod("close") + + when: + def result = handler.invoke(null, closeMethod, null) + + then: + 0 * target.close() + result == null + } + + def "test equals and hashCode"() { + given: + Session target = Mock(Session) + GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate) + CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template) + Method equalsMethod = Object.class.getMethod("equals", Object.class) + Method hashCodeMethod = Object.class.getMethod("hashCode") + def proxy = new Object() + + expect: + handler.invoke(proxy, equalsMethod, [proxy] as Object[]) == true + handler.invoke(proxy, equalsMethod, [new Object()] as Object[]) == false + handler.invoke(proxy, hashCodeMethod, null) == System.identityHashCode(proxy) + } + + def "test query preparation"() { + given: + Session target = Mock(Session) + GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate) + CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template) + + Query hibernateQuery = Mock(Query) + Method createQueryMethod = Session.class.getMethod("createQuery", String.class) + + when: + def result = handler.invoke(null, createQueryMethod, ["from Book"] as Object[]) + + then: + 1 * target.createQuery("from Book") >> hibernateQuery + 1 * template.prepareQuery(hibernateQuery) + result == hibernateQuery + } + + def "test criteria preparation"() { + given: + Session target = Mock(Session) + GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate) + CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template) + + Query jpaQuery = Mock(Query) + Method createQueryMethod = Session.class.getMethod("createQuery", String.class, Class.class) + + when: + def result = handler.invoke(null, createQueryMethod, ["from Book", Object.class] as Object[]) + + then: + 1 * target.createQuery("from Book", Object.class) >> jpaQuery + 1 * template.prepareCriteria(jpaQuery) + result == jpaQuery + } +}
