This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit df955a61170058d334059fd630a951d42490b21d Author: Walter B Duque de Estrada <[email protected]> AuthorDate: Tue Jan 27 08:37:02 2026 -0600 progress --- .../orm/hibernate/cfg/GrailsDomainBinder.java | 105 +------------ .../orm/hibernate/cfg/GrailsDomainBinder.java | 106 +------------ grails-data-hibernate7/core/01.txt | 5 +- .../orm/hibernate/cfg/GrailsDomainBinder.java | 175 +++++---------------- .../orm/hibernate/cfg/MappingCacheHolder.java | 4 +- .../collectionType/BagCollectionType.java | 28 ++++ .../collectionType/CollectionHolder.java | 27 ++++ .../collectionType/CollectionType.java | 82 ++++++++++ .../collectionType/ListCollectionType.java | 29 ++++ .../collectionType/MapCollectionType.java | 28 ++++ .../collectionType/SetCollectionType.java | 29 ++++ .../collectionType/SortedSetCollectionType.java | 30 ++++ .../gorm/specs/HibernateGormDatastoreSpec.groovy | 5 +- .../cfg/domainbinding/TypeNameProviderSpec.groovy | 3 +- 14 files changed, 303 insertions(+), 353 deletions(-) diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 1c5715728c..500f405ca4 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -119,6 +119,7 @@ import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.datastore.mapping.reflect.NameUtils; import org.grails.orm.hibernate.access.TraitPropertyAccessStrategy; +import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType; /** * Handles the binding Grails domain classes and properties to the Hibernate runtime meta model. @@ -157,6 +158,7 @@ public class GrailsDomainBinder implements MetadataContributor { } protected final CollectionType CT = new CollectionType(null, this) { + @Override public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { return null; } @@ -3499,109 +3501,6 @@ public class GrailsDomainBinder implements MetadataContributor { } } - /** - * A Collection type, for the moment only Set is supported - * - * @author Graeme - */ - static abstract class CollectionType { - - protected final Class<?> clazz; - protected final GrailsDomainBinder binder; - protected final MetadataBuildingContext buildingContext; - - protected CollectionType SET; - protected CollectionType LIST; - protected CollectionType BAG; - protected CollectionType MAP; - protected boolean initialized; - - protected final Map<Class<?>, CollectionType> INSTANCES = new HashMap<>(); - - public abstract Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; - - protected CollectionType(Class<?> clazz, GrailsDomainBinder binder) { - this.clazz = clazz; - this.binder = binder; - this.buildingContext = binder.getMetadataBuildingContext(); - } - - @Override - public String toString() { - return clazz.getName(); - } - - protected void createInstances() { - - if (initialized) { - return; - } - - initialized = true; - - SET = new CollectionType(Set.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(Set.class, SET); - INSTANCES.put(SortedSet.class, SET); - - LIST = new CollectionType(List.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.List coll = new org.hibernate.mapping.List(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(List.class, LIST); - - BAG = new CollectionType(java.util.Collection.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - Bag coll = new Bag(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(java.util.Collection.class, BAG); - - MAP = new CollectionType(Map.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(buildingContext, owner); - map.setTypeName(getTypeName(property)); - binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); - return map; - } - }; - INSTANCES.put(Map.class, MAP); - } - - public CollectionType collectionTypeForClass(Class<?> clazz) { - createInstances(); - return INSTANCES.get(clazz); - } - - public String getTypeName(ToMany property) { - return binder.getTypeName(property, binder.getPropertyConfig(property), getMapping(property.getOwner())); - } - } } diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 1bf910e7eb..09b3c5cbca 100644 --- a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -36,6 +36,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.NamingStrategyProvider; import org.grails.orm.hibernate.cfg.domainbinding.PersistentPropertyToPropertyConfig; import org.grails.orm.hibernate.cfg.domainbinding.SimpleValueColumnBinder; import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider; +import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType; import org.grails.orm.hibernate.cfg.domainbinding.*; import org.hibernate.FetchMode; import org.hibernate.MappingException; @@ -139,6 +140,7 @@ public class GrailsDomainBinder implements MetadataContributor { private static final NamingStrategyProvider NAMING_STRATEGY_PROVIDER = new NamingStrategyProvider(); private final CollectionType CT = new CollectionType(null, this) { + @Override public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { return null; } @@ -2247,110 +2249,6 @@ public class GrailsDomainBinder implements MetadataContributor { (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); } } - /** - * A Collection type, for the moment only Set is supported - * - * @author Graeme - */ - static abstract class CollectionType { - - private final Class<?> clazz; - private final GrailsDomainBinder binder; - private final MetadataBuildingContext buildingContext; - - private CollectionType SET; - private CollectionType LIST; - private CollectionType BAG; - private CollectionType MAP; - private boolean initialized; - - private final Map<Class<?>, CollectionType> INSTANCES = new HashMap<>(); - - public abstract Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; - - private CollectionType(Class<?> clazz, GrailsDomainBinder binder) { - this.clazz = clazz; - this.binder = binder; - this.buildingContext = binder.getMetadataBuildingContext(); - } - - @Override - public String toString() { - return clazz.getName(); - } - - private void createInstances() { - - if (initialized) { - return; - } - - initialized = true; - - SET = new CollectionType(Set.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(Set.class, SET); - INSTANCES.put(SortedSet.class, SET); - - LIST = new CollectionType(List.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.List coll = new org.hibernate.mapping.List(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(List.class, LIST); - - BAG = new CollectionType(java.util.Collection.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - Bag coll = new Bag(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(java.util.Collection.class, BAG); - - MAP = new CollectionType(Map.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(buildingContext, owner); - map.setTypeName(getTypeName(property)); - binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); - return map; - } - }; - INSTANCES.put(Map.class, MAP); - } - - public CollectionType collectionTypeForClass(Class<?> clazz) { - createInstances(); - return INSTANCES.get(clazz); - } - - public String getTypeName(ToMany property) { - Mapping mapping = new HibernateEntityWrapper().getMappedForm(property.getOwner()); - return new TypeNameProvider().getTypeName(property, mapping); - } - } } diff --git a/grails-data-hibernate7/core/01.txt b/grails-data-hibernate7/core/01.txt index 8ecab2edc3..9284d11cfa 100644 --- a/grails-data-hibernate7/core/01.txt +++ b/grails-data-hibernate7/core/01.txt @@ -1,11 +1,8 @@ AttachMethodSpec. Test attach method BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec. test unique constraint for the associated child object BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec. test unique constraint on root instance -CascadeBehaviorFetcherSpec. test cascade behavior fetcher for embedded association -CascadeBehaviorFetcherSpec. test cascade behavior fetcher for uni: String DirtyCheckingSpec. test relationships not marked dirty when domain objects are used JoinPerfSpec. test read performance with join query QueryEventsSpec. post-events are fired after queries are run QueryEventsSpec. pre-events are fired before queries are run -SessionCreationEventSpec. test event for new session - +SessionCreationEventSpec. test event for new session \ No newline at end of file diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 519719eb6d..6a904ef537 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -36,6 +36,8 @@ import org.grails.orm.hibernate.cfg.domainbinding.PersistentPropertyToPropertyCo import org.grails.orm.hibernate.cfg.domainbinding.SimpleValueColumnBinder; import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider; import org.grails.orm.hibernate.cfg.domainbinding.*; +import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder; +import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType; import org.hibernate.FetchMode; import org.hibernate.MappingException; @@ -52,7 +54,6 @@ import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.mapping.Backref; -import org.hibernate.mapping.Bag; import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; @@ -88,14 +89,12 @@ import org.springframework.util.StringUtils; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Optional; -import java.util.SortedSet; import java.util.StringTokenizer; import static java.util.Optional.ofNullable; @@ -132,6 +131,7 @@ public class GrailsDomainBinder public static final String JPA_DEFAULT_DISCRIMINATOR_TYPE = "DTYPE"; private final CollectionType CT = new CollectionType(null, this) { + @Override public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { return null; } @@ -144,6 +144,8 @@ public class GrailsDomainBinder private Closure defaultMapping; private PersistentEntityNamingStrategy namingStrategy; private MetadataBuildingContext metadataBuildingContext; + private MappingCacheHolder mappingCacheHolder; + private CollectionHolder collectionHolder; public JdbcEnvironment getJdbcEnvironment() { @@ -158,10 +160,11 @@ public class GrailsDomainBinder this.dataSourceName = dataSourceName; this.hibernateMappingContext = hibernateMappingContext; this.classBinding = classBinding; - MappingCacheHolder.getInstance().clear(); + mappingCacheHolder = MappingCacheHolder.getInstance(); + this.collectionHolder = new CollectionHolder(this); // pre-build mappings for (GrailsHibernatePersistentEntity persistentEntity : hibernateMappingContext.getHibernatePersistentEntities()) { - evaluateMapping(persistentEntity); + mappingCacheHolder.cacheMapping(persistentEntity); } } @@ -969,8 +972,8 @@ public class GrailsDomainBinder * @param mappings The Hibernate mappings instance * @param path */ - private void bindCollection(ToMany property, Collection collection, - PersistentClass owner, InFlightMetadataCollector mappings, String path, String sessionFactoryBeanName) { + public void bindCollection(ToMany property, Collection collection, + PersistentClass owner, InFlightMetadataCollector mappings, String path, String sessionFactoryBeanName) { // set role String propertyName = getNameForPropertyAndPath(property, path); @@ -1090,9 +1093,7 @@ public class GrailsDomainBinder } } - public void evaluateMapping(GrailsHibernatePersistentEntity persistentEntity) { - MappingCacheHolder.getInstance().cacheMapping(persistentEntity); - } + /** @@ -1133,7 +1134,7 @@ public class GrailsDomainBinder } // bind the sub classes entity.getChildEntities(dataSourceName) - .forEach(sub -> bindSubClass(sub, root, mappings, sessionFactoryBeanName, finalMapping)); + .forEach(sub -> bindSubClass(sub, root, mappings, sessionFactoryBeanName, finalMapping,mappingCacheHolder )); } addMultiTenantFilterIfNecessary(entity, root, mappings, sessionFactoryBeanName); @@ -1193,14 +1194,18 @@ public class GrailsDomainBinder /** * Binds a sub class. * - * @param sub The sub domain class instance - * @param parent The parent persistent class instance - * @param mappings The mappings instance - * @param sessionFactoryBeanName the session factory bean name + * @param sub The sub domain class instance + * @param parent The parent persistent class instance + * @param mappings The mappings instance + * @param sessionFactoryBeanName the session factory bean name + * @param mappingCacheHolder */ - private void bindSubClass(GrailsHibernatePersistentEntity sub, PersistentClass parent, - InFlightMetadataCollector mappings, String sessionFactoryBeanName,Mapping m) { - evaluateMapping(sub); + private void bindSubClass(GrailsHibernatePersistentEntity sub, + PersistentClass parent, + InFlightMetadataCollector mappings, + String sessionFactoryBeanName + , Mapping m, MappingCacheHolder mappingCacheHolder) { + mappingCacheHolder.cacheMapping(sub); Subclass subClass; boolean tablePerSubclass = m != null && !m.getTablePerHierarchy() && !m.isTablePerConcreteClass(); boolean tablePerConcreteClass = m != null && m.isTablePerConcreteClass(); @@ -1263,7 +1268,7 @@ public class GrailsDomainBinder if (!childEntities.isEmpty()) { // bind the sub classes sub.getChildEntities(dataSourceName) - .forEach(sub1 -> bindSubClass(sub1, subClass, mappings, sessionFactoryBeanName, m)); + .forEach(sub1 -> bindSubClass(sub1, subClass, mappings, sessionFactoryBeanName, m,mappingCacheHolder )); } } @@ -1598,7 +1603,7 @@ public class GrailsDomainBinder Value value = null; // see if it's a collection type - CollectionType collectionType = CT.collectionTypeForClass(currentGrailsProp.getType()); + CollectionType collectionType = collectionHolder.get(currentGrailsProp.getType()); Class<?> userType = getUserType(currentGrailsProp); @@ -1688,7 +1693,7 @@ public class GrailsDomainBinder for (Embedded association : embedded) { Value value = new Component(metadataBuildingContext, persistentClass); - bindComponent((Component) value, association, true, mappings, sessionFactoryBeanName); + bindComponent((Component) value, association, true, mappings, sessionFactoryBeanName,mappingCacheHolder ); Property property = createProperty(value, persistentClass, association, mappings); persistentClass.addProperty(property); } @@ -1730,21 +1735,22 @@ public class GrailsDomainBinder /** * Binds a Hibernate component type using the given GrailsDomainClassProperty instance * - * @param component The component to bind - * @param property The property - * @param isNullable Whether it is nullable or not - * @param mappings The Hibernate Mappings object - * @param sessionFactoryBeanName the session factory bean name + * @param component The component to bind + * @param property The property + * @param isNullable Whether it is nullable or not + * @param mappings The Hibernate Mappings object + * @param sessionFactoryBeanName the session factory bean name + * @param mappingCacheHolder */ private void bindComponent(Component component, Embedded property, - boolean isNullable, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + boolean isNullable, InFlightMetadataCollector mappings, String sessionFactoryBeanName, MappingCacheHolder mappingCacheHolder) { Class<?> type = property.getType(); String role = qualify(type.getName(), property.getName()); component.setRoleName(role); component.setComponentClassName(type.getName()); GrailsHibernatePersistentEntity domainClass = (GrailsHibernatePersistentEntity) property.getAssociatedEntity(); - evaluateMapping(domainClass); + mappingCacheHolder.cacheMapping(domainClass); final List<PersistentProperty> properties = domainClass.getPersistentProperties(); Table table = component.getOwner().getTable(); PersistentClass persistentClass = component.getOwner(); @@ -1770,7 +1776,7 @@ public class GrailsDomainBinder String path, Table table, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { Value value; // see if it's a collection type - CollectionType collectionType = CT.collectionTypeForClass(currentGrailsProp.getType()); + CollectionType collectionType = collectionHolder.get(currentGrailsProp.getType()); if (collectionType != null) { // create collection Collection collection = collectionType.create((ToMany) currentGrailsProp, persistentClass, @@ -1800,7 +1806,7 @@ public class GrailsDomainBinder } else if (currentGrailsProp instanceof Embedded) { value = new Component(metadataBuildingContext, persistentClass); - bindComponent((Component) value, (Embedded) currentGrailsProp, true, mappings, sessionFactoryBeanName); + bindComponent((Component) value, (Embedded) currentGrailsProp, true, mappings, sessionFactoryBeanName,mappingCacheHolder ); } else { if (LOG.isDebugEnabled()) @@ -2071,114 +2077,5 @@ public class GrailsDomainBinder (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); } } - /** - * A Collection type, for the moment only Set is supported - * - * @author Graeme - */ - static abstract class CollectionType { - - private final Class<?> clazz; - private final GrailsDomainBinder binder; - private final MetadataBuildingContext buildingContext; - - private CollectionType SET; - private CollectionType LIST; - private CollectionType BAG; - private CollectionType MAP; - private boolean initialized; - - private final Map<Class<?>, CollectionType> INSTANCES = new HashMap<>(); - - public abstract Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; - - private CollectionType(Class<?> clazz, GrailsDomainBinder binder) { - this.clazz = clazz; - this.binder = binder; - this.buildingContext = binder.getMetadataBuildingContext(); - } - - @Override - public String toString() { - return clazz.getName(); - } - - private void createInstances() { - - if (initialized) { - return; - } - - initialized = true; - - SET = new CollectionType(Set.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(Set.class, SET); - INSTANCES.put(SortedSet.class, SET); - - LIST = new CollectionType(List.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.List coll = new org.hibernate.mapping.List(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(List.class, LIST); - - BAG = new CollectionType(java.util.Collection.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - Bag coll = new Bag(buildingContext, owner); - coll.setCollectionTable(owner.getTable()); - coll.setTypeName(getTypeName(property)); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(java.util.Collection.class, BAG); - - MAP = new CollectionType(Map.class, binder) { - @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(buildingContext, owner); - map.setTypeName(getTypeName(property)); - binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); - return map; - } - }; - INSTANCES.put(Map.class, MAP); - } - - public CollectionType collectionTypeForClass(Class<?> clazz) { - createInstances(); - return INSTANCES.get(clazz); - } - - public String getTypeName(ToMany property) { - Mapping mapping = null; - GrailsHibernatePersistentEntity domainClass = (GrailsHibernatePersistentEntity) property.getOwner(); - if (domainClass != null) { - mapping = domainClass.getMappedForm(); - } - return new TypeNameProvider().getTypeName(property, mapping); - } - - } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/MappingCacheHolder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/MappingCacheHolder.java index dcbf863b59..4250b23eb4 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/MappingCacheHolder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/MappingCacheHolder.java @@ -36,7 +36,9 @@ public class MappingCacheHolder { * @param entity The domain class in question */ public void cacheMapping(GrailsHibernatePersistentEntity entity) { - MAPPING_CACHE.put(entity.getJavaClass(), entity.getMappedForm()); + if (entity != null) { + MAPPING_CACHE.put(entity.getJavaClass(), entity.getMappedForm()); + } } public void clear() { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/BagCollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/BagCollectionType.java new file mode 100644 index 0000000000..c21807a38b --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/BagCollectionType.java @@ -0,0 +1,28 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.Bag; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public class BagCollectionType extends CollectionType { + + public BagCollectionType(GrailsDomainBinder binder) { + super(java.util.Collection.class, binder); + } + + @Override + public Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + Bag coll = new Bag(buildingContext, owner); + coll.setCollectionTable(owner.getTable()); + coll.setTypeName(getTypeName(property)); + binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); + return coll; + } + +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionHolder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionHolder.java new file mode 100644 index 0000000000..1f76cc5f92 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionHolder.java @@ -0,0 +1,27 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public record CollectionHolder(Map<Class<?>, CollectionType> map) { + + public CollectionHolder(GrailsDomainBinder binder) { + this(Map.ofEntries( + Map.entry(Set.class, new SetCollectionType(binder)), + Map.entry(SortedSet.class, new SetCollectionType(binder)), + Map.entry(List.class, new ListCollectionType(binder)), + Map.entry(Collection.class, new BagCollectionType(binder)), + Map.entry(Map.class, new MapCollectionType(binder)) + )); + } + + public CollectionType get(Class<?> collectionClass) { + return map.get(collectionClass); + } +} + diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionType.java new file mode 100644 index 0000000000..af3b360d6f --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/CollectionType.java @@ -0,0 +1,82 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.mapping.Bag; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; +import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity; +import org.grails.orm.hibernate.cfg.Mapping; +import org.grails.orm.hibernate.cfg.domainbinding.TypeNameProvider; + +/** + * A Collection type, for the moment only Set is supported + * + * @author Graeme + */ +public abstract class CollectionType { + + protected final Class<?> clazz; + protected final GrailsDomainBinder binder; + protected final MetadataBuildingContext buildingContext; + + private boolean initialized; + + private final Map<Class<?>, CollectionType> INSTANCES = new HashMap<>(); + + public abstract Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; + + protected CollectionType(Class<?> clazz, GrailsDomainBinder binder) { + this.clazz = clazz; + this.binder = binder; + this.buildingContext = binder.getMetadataBuildingContext(); + } + + @Override + public String toString() { + return clazz.getName(); + } + + private void createInstances() { + + if (initialized) { + return; + } + + initialized = true; + + CollectionType set = new SetCollectionType(binder); + INSTANCES.put(Set.class, set); + INSTANCES.put(SortedSet.class, set); + + INSTANCES.put(List.class, new ListCollectionType(binder)); + INSTANCES.put(java.util.Collection.class, new BagCollectionType(binder)); + INSTANCES.put(Map.class, new MapCollectionType(binder)); + } + + public CollectionType collectionTypeForClass(Class<?> clazz) { + createInstances(); + return INSTANCES.get(clazz); + } + + public String getTypeName(ToMany property) { + Mapping mapping = null; + GrailsHibernatePersistentEntity domainClass = (GrailsHibernatePersistentEntity) property.getOwner(); + if (domainClass != null) { + mapping = domainClass.getMappedForm(); + } + return new TypeNameProvider().getTypeName(property, mapping); + } + +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/ListCollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/ListCollectionType.java new file mode 100644 index 0000000000..68fd9e0baf --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/ListCollectionType.java @@ -0,0 +1,29 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public class ListCollectionType extends CollectionType { + + public ListCollectionType(GrailsDomainBinder binder) { + super(List.class, binder); + } + + @Override + public Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + org.hibernate.mapping.List coll = new org.hibernate.mapping.List(buildingContext, owner); + coll.setCollectionTable(owner.getTable()); + coll.setTypeName(getTypeName(property)); + binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); + return coll; + } + +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/MapCollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/MapCollectionType.java new file mode 100644 index 0000000000..22de22b5c9 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/MapCollectionType.java @@ -0,0 +1,28 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.Map; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public class MapCollectionType extends CollectionType { + + public MapCollectionType(GrailsDomainBinder binder) { + super(Map.class, binder); + } + + @Override + public Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(buildingContext, owner); + map.setTypeName(getTypeName(property)); + binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); + return map; + } + +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SetCollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SetCollectionType.java new file mode 100644 index 0000000000..956521a785 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SetCollectionType.java @@ -0,0 +1,29 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.Set; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public class SetCollectionType extends CollectionType { + + public SetCollectionType(GrailsDomainBinder binder) { + super(Set.class, binder); + } + + @Override + public Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); + coll.setCollectionTable(owner.getTable()); + coll.setTypeName(getTypeName(property)); + binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); + return coll; + } + +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SortedSetCollectionType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SortedSetCollectionType.java new file mode 100644 index 0000000000..b92252f849 --- /dev/null +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/collectionType/SortedSetCollectionType.java @@ -0,0 +1,30 @@ +package org.grails.orm.hibernate.cfg.domainbinding.collectionType; + +import java.util.Set; +import java.util.SortedSet; + +import org.hibernate.MappingException; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.Collection; +import org.hibernate.mapping.PersistentClass; + +import org.grails.datastore.mapping.model.types.ToMany; +import org.grails.orm.hibernate.cfg.GrailsDomainBinder; + +public class SortedSetCollectionType extends CollectionType { + + public SortedSetCollectionType(GrailsDomainBinder binder) { + super(SortedSet.class, binder); + } + + @Override + public Collection create(ToMany property, PersistentClass owner, + String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); + coll.setCollectionTable(owner.getTable()); + coll.setTypeName(getTypeName(property)); + binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); + return coll; + } + +} diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy index 2c7975252e..e57f3c9410 100644 --- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy @@ -9,6 +9,7 @@ import org.grails.orm.hibernate.cfg.GrailsDomainBinder import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity import org.grails.orm.hibernate.cfg.HibernateMappingContext import org.grails.orm.hibernate.cfg.HibernatePersistentEntity +import org.grails.orm.hibernate.cfg.MappingCacheHolder import org.grails.orm.hibernate.query.HibernateQuery import org.hibernate.boot.MetadataSources @@ -74,7 +75,9 @@ class HibernateGormDatastoreSpec extends GrailsDataTckSpec<GrailsDataHibernate7T GrailsHibernatePersistentEntity createPersistentEntity(Class clazz, GrailsDomainBinder binder) { def entity = getMappingContext().addPersistentEntity(clazz) as GrailsHibernatePersistentEntity - binder.evaluateMapping(entity) + if (entity != null) { + MappingCacheHolder.getInstance().cacheMapping(entity) + } entity } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProviderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProviderSpec.groovy index b7e07c2bae..c8dc778b88 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProviderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProviderSpec.groovy @@ -4,6 +4,7 @@ import grails.gorm.specs.HibernateGormDatastoreSpec import grails.persistence.Entity import org.grails.orm.hibernate.cfg.HibernatePersistentEntity import org.grails.orm.hibernate.cfg.Mapping +import org.grails.orm.hibernate.cfg.MappingCacheHolder import org.grails.orm.hibernate.cfg.PropertyConfig import org.hibernate.type.descriptor.java.BasicJavaType import org.hibernate.type.descriptor.jdbc.JdbcType @@ -50,7 +51,7 @@ class TypeNameProviderSpec extends HibernateGormDatastoreSpec { when: def grailsDomainBinder = getGrailsDomainBinder() def persistentEntity = getMappingContext().addPersistentEntity(Employee) as HibernatePersistentEntity - grailsDomainBinder.evaluateMapping(persistentEntity) + MappingCacheHolder.getInstance().cacheMapping(persistentEntity) def property = persistentEntity.getPersistentProperties()[0] Mapping mapping = new Mapping() mapping.setUserTypes([(Salary): SalaryType])
