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 c74f868890a0d4945402d748c9121e914cfd6c7f
Author: Walter B Duque de Estrada <[email protected]>
AuthorDate: Sat Jan 31 13:39:05 2026 -0600

    remove TypeNameProvider
---
 .../orm/hibernate/cfg/GrailsDomainBinder.java      |  10 +-
 .../cfg/GrailsHibernatePersistentEntity.java       |   5 +
 .../cfg/GrailsHibernatePersistentProperty.java     |  21 ++
 .../orm/hibernate/cfg/HibernateBasicProperty.java  |  16 ++
 .../orm/hibernate/cfg/HibernateCustomProperty.java |  17 ++
 .../cfg/HibernateEmbeddedCollectionProperty.java   |  16 ++
 .../hibernate/cfg/HibernateEmbeddedProperty.java   |  16 ++
 .../hibernate/cfg/HibernateIdentityProperty.java   |  16 ++
 .../hibernate/cfg/HibernateManyToManyProperty.java |  16 ++
 .../hibernate/cfg/HibernateManyToOneProperty.java  |  16 ++
 .../orm/hibernate/cfg/HibernateMappingContext.java |  98 +++++++++
 .../hibernate/cfg/HibernateOneToManyProperty.java  |  16 ++
 .../hibernate/cfg/HibernateOneToOneProperty.java   |  16 ++
 .../hibernate/cfg/HibernatePersistentEntity.java   |   6 +
 .../orm/hibernate/cfg/HibernateSimpleProperty.java |  16 ++
 .../hibernate/cfg/HibernateTenantIdProperty.java   |  16 ++
 .../cfg/domainbinding/EnumTypeBinder.java          |   3 +-
 .../cfg/domainbinding/SimpleValueBinder.java       |   9 +-
 .../cfg/domainbinding/TypeNameProvider.java        |  32 ---
 .../collectionType/CollectionType.java             |   6 +-
 .../cfg/domainbinding/SimpleValueBinderSpec.groovy |  25 ++-
 .../cfg/domainbinding/TypeNameProviderSpec.groovy  |  82 -------
 .../mapping/model/AbstractClassMapping.java        |   6 +-
 .../mapping/model/AbstractPersistentEntity.java    |   2 +-
 .../datastore/mapping/model/ClassMapping.java      |   2 +-
 .../mapping/model/DefaultIdentityMapping.java      |  68 ++++++
 ...ityMapping.java => DefaultPropertyMapping.java} |  37 ++--
 .../datastore/mapping/model/IdentityMapping.java   |   5 +-
 .../datastore/mapping/model/MappingFactory.java    | 236 +++++----------------
 .../mapping/model/PersistentProperty.java          |   2 +-
 .../datastore/mapping/model/types/Custom.java      |   3 +-
 .../model/types/mapping/BasicWithMapping.java      |  58 +++++
 .../model/types/mapping/CustomWithMapping.java     |  59 ++++++
 .../mapping/EmbeddedCollectionWithMapping.java     |  64 ++++++
 .../model/types/mapping/EmbeddedWithMapping.java   |  64 ++++++
 .../model/types/mapping/IdentityWithMapping.java   |  58 +++++
 .../model/types/mapping/ManyToManyWithMapping.java |  64 ++++++
 .../model/types/mapping/ManyToOneWithMapping.java  |  64 ++++++
 .../model/types/mapping/OneToManyWithMapping.java  |  64 ++++++
 .../model/types/mapping/OneToOneWithMapping.java   |  64 ++++++
 .../model/types/mapping/PropertyWithMapping.java   |  10 +
 .../model/types/mapping/SimpleWithMapping.java     |  58 +++++
 .../model/types/mapping/TenantIdWithMapping.java   |  58 +++++
 43 files changed, 1171 insertions(+), 349 deletions(-)

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 f01014bc05..043f99e247 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
@@ -33,7 +33,6 @@ import 
org.grails.orm.hibernate.cfg.domainbinding.EnumTypeBinder;
 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.*;
 import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder;
 import 
org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType;
@@ -285,7 +284,7 @@ public class GrailsDomainBinder
             if (domainClass != null) {
                 mapping = domainClass.getMappedForm();
             }
-            String typeName = new TypeNameProvider().getTypeName(property, 
mapping);
+            String typeName = property instanceof 
GrailsHibernatePersistentProperty ghpp ? ghpp.getTypeName(mapping) : null;
             if (typeName == null ) {
 
                 if(property instanceof Basic) {
@@ -738,8 +737,7 @@ public class GrailsDomainBinder
                 if (domainClass != null) {
                     mapping = domainClass.getMappedForm();
                 }
-                ;
-                String typeName = new TypeNameProvider().getTypeName(property, 
mapping);
+                String typeName = property instanceof 
GrailsHibernatePersistentProperty ghpp ? ghpp.getTypeName(mapping) : null;
                 if (typeName == null) {
                     Type type = 
mappings.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType(className);
                     if (type != null) {
@@ -1538,7 +1536,7 @@ public class GrailsDomainBinder
             new 
SimpleValueBinder(namingStrategy).bindSimpleValue(currentGrailsProp, null, 
(SimpleValue) value, EMPTY_PATH);
         }
         else if (collectionType != null) {
-            String typeName = new 
TypeNameProvider().getTypeName(currentGrailsProp, gormMapping);
+            String typeName = currentGrailsProp instanceof 
GrailsHibernatePersistentProperty ghpp ? ghpp.getTypeName(gormMapping) : null;
             if ("serializable".equals(typeName)) {
                 value = new BasicValue(metadataBuildingContext, table);
                 boolean nullable = currentGrailsProp.isNullable();
@@ -1661,7 +1659,7 @@ public class GrailsDomainBinder
                     mapping = domainClass.getMappedForm();
                 }
 
-                return new TypeNameProvider().getTypeName(property, mapping);
+                return property instanceof GrailsHibernatePersistentProperty 
ghpp ? ghpp.getTypeName(mapping) : null;
 
             }
 
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
index 80161d7c43..a06db90127 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentEntity.java
@@ -30,6 +30,11 @@ public interface GrailsHibernatePersistentEntity extends 
PersistentEntity {
     boolean isAbstract();
 
 
+    @SuppressWarnings("unchecked")
+    default List<GrailsHibernatePersistentProperty> 
getHibernatePersistentProperties() {
+        return (List) getPersistentProperties();
+    }
+
     default List<GrailsHibernatePersistentEntity> getChildEntities(String 
dataSourceName) {
         return getMappingContext()
                 .getDirectChildEntities(this)
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java
new file mode 100644
index 0000000000..ba14306a4b
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java
@@ -0,0 +1,21 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.PersistentProperty;
+
+import java.util.Optional;
+
+/**
+ * Interface for Hibernate persistent properties
+ */
+public interface GrailsHibernatePersistentProperty extends 
PersistentProperty<PropertyConfig> {
+
+    /**
+     * @param mapping The mapping
+     * @return The type name
+     */
+    default String getTypeName(Mapping mapping) {
+        return Optional.ofNullable(getMappedForm().getType())
+                .map(typeObj -> typeObj instanceof Class<?> clazz ? 
clazz.getName() : typeObj.toString())
+                .orElseGet(() -> mapping != null ? 
mapping.getTypeName(getType()) : null);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateBasicProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateBasicProperty.java
new file mode 100644
index 0000000000..51c126c0a1
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateBasicProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.BasicWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.Basic}
+ */
+public class HibernateBasicProperty extends BasicWithMapping<PropertyConfig> 
implements GrailsHibernatePersistentProperty {
+    public HibernateBasicProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateCustomProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateCustomProperty.java
new file mode 100644
index 0000000000..2b7dd11e6f
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateCustomProperty.java
@@ -0,0 +1,17 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.CustomWithMapping;
+
+import java.beans.PropertyDescriptor;
+import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.Custom}
+ */
+public class HibernateCustomProperty extends CustomWithMapping<PropertyConfig> 
implements GrailsHibernatePersistentProperty {
+    public HibernateCustomProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, CustomTypeMarshaller<?, ?, ?> 
customTypeMarshaller) {
+        super(entity, context, property, customTypeMarshaller);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedCollectionProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedCollectionProperty.java
new file mode 100644
index 0000000000..9c770dc5ee
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedCollectionProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import 
org.grails.datastore.mapping.model.types.mapping.EmbeddedCollectionWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.EmbeddedCollection}
+ */
+public class HibernateEmbeddedCollectionProperty extends 
EmbeddedCollectionWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateEmbeddedCollectionProperty(PersistentEntity entity, 
MappingContext context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedProperty.java
new file mode 100644
index 0000000000..009dea50a7
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateEmbeddedProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.EmbeddedWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.Embedded}
+ */
+public class HibernateEmbeddedProperty extends 
EmbeddedWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateEmbeddedProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateIdentityProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateIdentityProperty.java
new file mode 100644
index 0000000000..6deb95e877
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateIdentityProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.IdentityWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.Identity}
+ */
+public class HibernateIdentityProperty extends 
IdentityWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateIdentityProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToManyProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToManyProperty.java
new file mode 100644
index 0000000000..0d7a3e32a8
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToManyProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.ManyToManyWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.ManyToMany}
+ */
+public class HibernateManyToManyProperty extends 
ManyToManyWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateManyToManyProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToOneProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToOneProperty.java
new file mode 100644
index 0000000000..b357b02aff
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateManyToOneProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.ManyToOneWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.ManyToOne}
+ */
+public class HibernateManyToOneProperty extends 
ManyToOneWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateManyToOneProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java
index d0e3d04cbc..b331e14d25 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java
@@ -23,14 +23,17 @@ import org.grails.datastore.gorm.GormEntity;
 import org.grails.datastore.mapping.config.AbstractGormMappingFactory;
 import org.grails.datastore.mapping.config.Property;
 import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder;
+import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller;
 import org.grails.datastore.mapping.model.*;
 import org.grails.datastore.mapping.model.config.GormProperties;
 import 
org.grails.datastore.mapping.model.config.JpaMappingConfigurationStrategy;
+import org.grails.datastore.mapping.model.types.*;
 import org.grails.datastore.mapping.reflect.ClassUtils;
 import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings;
 import org.grails.orm.hibernate.proxy.HibernateProxyHandler;
 import org.springframework.validation.Errors;
 
+import java.beans.PropertyDescriptor;
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -209,6 +212,101 @@ public class HibernateMappingContext extends 
AbstractMappingContext {
             return new HibernateMappingBuilder(mapping, entity.getName(), 
defaultConstraints);
         }
 
+        @Override
+        public 
org.grails.datastore.mapping.model.types.Identity<PropertyConfig> 
createIdentity(PersistentEntity owner, MappingContext context, 
PropertyDescriptor pd) {
+            HibernateIdentityProperty identity = new 
HibernateIdentityProperty(owner, context, pd);
+            identity.setMapping(createPropertyMapping(identity, owner));
+            return identity;
+        }
+
+        @Override
+        public 
org.grails.datastore.mapping.model.types.TenantId<PropertyConfig> 
createTenantId(PersistentEntity owner, MappingContext context, 
PropertyDescriptor pd) {
+            HibernateTenantIdProperty tenantId = new 
HibernateTenantIdProperty(owner, context, pd);
+            tenantId.setMapping(createDerivedPropertyMapping(tenantId, owner));
+            return tenantId;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.Custom<PropertyConfig> 
createCustom(PersistentEntity owner, MappingContext context, PropertyDescriptor 
pd) {
+            final Class<?> propertyType = pd.getPropertyType();
+            CustomTypeMarshaller customTypeMarshaller = 
findCustomType(context, propertyType);
+            if (customTypeMarshaller == null && propertyType.isEnum()) {
+                customTypeMarshaller = findCustomType(context, Enum.class);
+            }
+            HibernateCustomProperty custom = new 
HibernateCustomProperty(owner, context, pd, customTypeMarshaller);
+            custom.setMapping(createPropertyMapping(custom, owner));
+            return custom;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.Simple<PropertyConfig> 
createSimple(PersistentEntity owner, MappingContext context, PropertyDescriptor 
pd) {
+            HibernateSimpleProperty simple = new 
HibernateSimpleProperty(owner, context, pd);
+            simple.setMapping(createPropertyMapping(simple, owner));
+            return simple;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.ToOne 
createOneToOne(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateOneToOneProperty oneToOne = new 
HibernateOneToOneProperty(entity, context, property);
+            oneToOne.setMapping(createPropertyMapping(oneToOne, entity));
+            return oneToOne;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.ToOne 
createManyToOne(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateManyToOneProperty manyToOne = new 
HibernateManyToOneProperty(entity, context, property);
+            manyToOne.setMapping(createPropertyMapping(manyToOne, entity));
+            return manyToOne;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.OneToMany 
createOneToMany(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateOneToManyProperty oneToMany = new 
HibernateOneToManyProperty(entity, context, property);
+            oneToMany.setMapping(createPropertyMapping(oneToMany, entity));
+            return oneToMany;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.ManyToMany 
createManyToMany(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateManyToManyProperty manyToMany = new 
HibernateManyToManyProperty(entity, context, property);
+            manyToMany.setMapping(createPropertyMapping(manyToMany, entity));
+            return manyToMany;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.Embedded 
createEmbedded(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateEmbeddedProperty embedded = new 
HibernateEmbeddedProperty(entity, context, property);
+            embedded.setMapping(createPropertyMapping(embedded, entity));
+            return embedded;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.EmbeddedCollection 
createEmbeddedCollection(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+            HibernateEmbeddedCollectionProperty embedded = new 
HibernateEmbeddedCollectionProperty(entity, context, property);
+            embedded.setMapping(createPropertyMapping(embedded, entity));
+            return embedded;
+        }
+
+        @Override
+        public org.grails.datastore.mapping.model.types.Basic 
createBasicCollection(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property, Class collectionType) {
+            HibernateBasicProperty basic = new HibernateBasicProperty(entity, 
context, property);
+            basic.setMapping(createPropertyMapping(basic, entity));
+
+            CustomTypeMarshaller customTypeMarshaller = 
findCustomType(context, property.getPropertyType());
+            if (collectionType != null && collectionType.isEnum()) {
+                customTypeMarshaller = findCustomType(context, collectionType);
+                if (customTypeMarshaller == null) {
+                    customTypeMarshaller = findCustomType(context, Enum.class);
+                }
+            }
+
+            if (customTypeMarshaller != null) {
+                basic.setCustomTypeMarshaller(customTypeMarshaller);
+            }
+
+            return basic;
+        }
+
         @Override
         public IdentityMapping createIdentityMapping(final ClassMapping 
classMapping) {
             final Mapping mappedForm = 
createMappedForm(classMapping.getEntity());
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToManyProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToManyProperty.java
new file mode 100644
index 0000000000..65c01a6c92
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToManyProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.OneToManyWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.OneToMany}
+ */
+public class HibernateOneToManyProperty extends 
OneToManyWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateOneToManyProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToOneProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToOneProperty.java
new file mode 100644
index 0000000000..d8df3be439
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateOneToOneProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.OneToOneWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.OneToOne}
+ */
+public class HibernateOneToOneProperty extends 
OneToOneWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateOneToOneProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java
index 4e5eb51174..37c87e35f5 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java
@@ -67,5 +67,11 @@ public class HibernatePersistentEntity extends 
AbstractPersistentEntity<Mapping>
                 && isRoot();
     }
 
+    @Override
+    @SuppressWarnings("unchecked")
+    public java.util.List<GrailsHibernatePersistentProperty> 
getHibernatePersistentProperties() {
+        return (java.util.List) persistentProperties;
+    }
+
 
 }
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateSimpleProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateSimpleProperty.java
new file mode 100644
index 0000000000..addc4a1268
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateSimpleProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.SimpleWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.Simple}
+ */
+public class HibernateSimpleProperty extends SimpleWithMapping<PropertyConfig> 
implements GrailsHibernatePersistentProperty {
+    public HibernateSimpleProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateTenantIdProperty.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateTenantIdProperty.java
new file mode 100644
index 0000000000..2e58df7362
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateTenantIdProperty.java
@@ -0,0 +1,16 @@
+package org.grails.orm.hibernate.cfg;
+
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.types.mapping.TenantIdWithMapping;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * Hibernate implementation of {@link 
org.grails.datastore.mapping.model.types.TenantId}
+ */
+public class HibernateTenantIdProperty extends 
TenantIdWithMapping<PropertyConfig> implements 
GrailsHibernatePersistentProperty {
+    public HibernateTenantIdProperty(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+}
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/EnumTypeBinder.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/EnumTypeBinder.java
index 3e109620a5..94201c6ea4 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/EnumTypeBinder.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/EnumTypeBinder.java
@@ -3,6 +3,7 @@ package org.grails.orm.hibernate.cfg.domainbinding;
 import org.grails.datastore.mapping.model.PersistentProperty;
 import org.grails.orm.hibernate.cfg.ColumnConfig;
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity;
+import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty;
 import org.grails.orm.hibernate.cfg.IdentityEnumType;
 import org.grails.orm.hibernate.cfg.Mapping;
 import org.grails.orm.hibernate.cfg.PropertyConfig;
@@ -47,7 +48,7 @@ public class EnumTypeBinder {
         String enumType = pc.getEnumType();
         Properties enumProperties = new Properties();
         enumProperties.put(ENUM_CLASS_PROP, propertyType.getName());
-        String typeName = new TypeNameProvider().getTypeName(property, 
ownerMapping);
+        String typeName = property instanceof 
GrailsHibernatePersistentProperty ghpp ? ghpp.getTypeName(ownerMapping) : null;
         if (typeName != null) {
             simpleValue.setTypeName(typeName);
         } else {
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
index 1e1cfb4847..6484f11bca 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinder.java
@@ -15,6 +15,7 @@ import org.grails.datastore.mapping.model.PersistentProperty;
 import org.grails.datastore.mapping.model.types.TenantId;
 import org.grails.orm.hibernate.cfg.ColumnConfig;
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity;
+import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty;
 import org.grails.orm.hibernate.cfg.Mapping;
 import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy;
 import org.grails.orm.hibernate.cfg.PropertyConfig;
@@ -26,7 +27,6 @@ public class SimpleValueBinder {
     private final ColumnConfigToColumnBinder columnConfigToColumnBinder ;
     private final ColumnBinder columnBinder;
     private final PersistentPropertyToPropertyConfig 
persistentPropertyToPropertyConfig;
-    private final TypeNameProvider typeNameProvider;
 
 
     private static final String SEQUENCE_KEY = 
GrailsSequenceGeneratorEnum.SEQUENCE.toString();
@@ -40,19 +40,16 @@ public class SimpleValueBinder {
         this.persistentPropertyToPropertyConfig = 
persistentPropertyToPropertyConfig;
         this.columnConfigToColumnBinder = new ColumnConfigToColumnBinder();
         this.columnBinder = new ColumnBinder(namingStrategy);
-        this.typeNameProvider = new TypeNameProvider();
     }
 
     protected SimpleValueBinder(PersistentEntityNamingStrategy namingStrategy,
                                 ColumnConfigToColumnBinder 
columnConfigToColumnBinder,
                                 ColumnBinder columnBinder,
-                                PersistentPropertyToPropertyConfig 
persistentPropertyToPropertyConfig,
-                                TypeNameProvider typeNameProvider) {
+                                PersistentPropertyToPropertyConfig 
persistentPropertyToPropertyConfig) {
         this.namingStrategy = namingStrategy;
         this.columnConfigToColumnBinder = columnConfigToColumnBinder;
         this.columnBinder = columnBinder;
         this.persistentPropertyToPropertyConfig = 
persistentPropertyToPropertyConfig;
-        this.typeNameProvider = typeNameProvider;
     }
 
 
@@ -77,7 +74,7 @@ public class SimpleValueBinder {
         if (property.getOwner() instanceof GrailsHibernatePersistentEntity 
persistentEntity) {
             mapping = persistentEntity.getMappedForm();
         }
-        final String typeName = typeNameProvider.getTypeName(property, 
mapping);
+        final String typeName = property instanceof 
GrailsHibernatePersistentProperty ghpp ? ghpp.getTypeName(mapping) : null;
         if (typeName == null) {
             Class<?> type = property.getType();
             if (type != null) {
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProvider.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProvider.java
deleted file mode 100644
index ce7900fb83..0000000000
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProvider.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.grails.orm.hibernate.cfg.domainbinding;
-
-import jakarta.validation.constraints.NotNull;
-import org.grails.datastore.mapping.model.PersistentProperty;
-import org.grails.orm.hibernate.cfg.Mapping;
-import org.grails.orm.hibernate.cfg.PropertyConfig;
-
-import static java.util.Optional.of;
-import static java.util.Optional.ofNullable;
-
-public class TypeNameProvider {
-
-    public String getTypeName(@jakarta.annotation.Nonnull PersistentProperty 
property
-            , @NotNull Mapping mapping) {
-        return of(property)
-                .map(PersistentProperty::getMappedForm)
-                .map(PropertyConfig.class::cast)
-                .map(PropertyConfig::getType)
-                .map(typeObj -> typeObj instanceof Class<?> clazz ?
-                        clazz.getName() : typeObj.toString()
-                )
-                .orElseGet(() -> property != null && mapping != null
-                        ? mapping.getTypeName(property.getType()) : null
-                );
-
-    }
-
-
-}
-
-
-
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
index cf85d45193..04ae10a0c8 100644
--- 
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
@@ -18,8 +18,8 @@ import jakarta.annotation.Nonnull;
 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.GrailsHibernatePersistentProperty;
 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
@@ -72,10 +72,10 @@ public abstract class CollectionType {
         return INSTANCES.get(clazz);
     }
 
-    public String getTypeName(ToMany property) {
+    public String getTypeName(ToMany<?> property) {
         GrailsHibernatePersistentEntity domainClass = 
(GrailsHibernatePersistentEntity) property.getOwner();
         Mapping mapping = domainClass.getMappedForm();
-        return new TypeNameProvider().getTypeName(property, mapping);
+        return property instanceof GrailsHibernatePersistentProperty ghpp ? 
ghpp.getTypeName(mapping) : null;
     }
 
 }
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
index b7744f98ac..c469b1659e 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy
@@ -4,6 +4,7 @@ import org.grails.datastore.mapping.model.PersistentProperty
 import org.grails.datastore.mapping.model.types.TenantId
 import org.grails.orm.hibernate.cfg.ColumnConfig
 import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentEntity
+import org.grails.orm.hibernate.cfg.GrailsHibernatePersistentProperty
 import org.grails.orm.hibernate.cfg.Mapping
 import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy
 import org.grails.orm.hibernate.cfg.PropertyConfig
@@ -18,17 +19,15 @@ class SimpleValueBinderSpec extends Specification {
     def columnConfigToColumnBinder = Mock(ColumnConfigToColumnBinder)
     def columnBinder = Mock(ColumnBinder)
     def persistentPropertyToPropertyConfig = 
Mock(PersistentPropertyToPropertyConfig)
-    def typeNameProvider = Mock(TypeNameProvider)
 
     def binder = new SimpleValueBinder(namingStrategy,
             columnConfigToColumnBinder,
             columnBinder,
-            persistentPropertyToPropertyConfig,
-            typeNameProvider)
+            persistentPropertyToPropertyConfig)
 
     def "sets type from provider when present and applies type params"() {
         given:
-        def prop = Mock(PersistentProperty)
+        def prop = Mock(GrailsHibernatePersistentProperty)
         def owner = Mock(GrailsHibernatePersistentEntity)
         def mapping = Mock(Mapping)
         def pc = Mock(PropertyConfig)
@@ -40,7 +39,7 @@ class SimpleValueBinderSpec extends Specification {
         persistentPropertyToPropertyConfig.toPropertyConfig(prop) >> pc
         prop.getOwner() >> owner
         owner.getMappedForm() >> mapping
-        typeNameProvider.getTypeName(prop, mapping) >> "custom.Type"
+        prop.getTypeName(mapping) >> "custom.Type"
         pc.getTypeParams() >> props
         pc.isDerived() >> false
         pc.getColumns() >> null
@@ -65,7 +64,7 @@ class SimpleValueBinderSpec extends Specification {
 
     def "falls back to property type when provider returns null"() {
         given:
-        def prop = Mock(PersistentProperty)
+        def prop = Mock(GrailsHibernatePersistentProperty)
         def owner = Mock(GrailsHibernatePersistentEntity)
         def mapping = Mock(Mapping)
         def pc = Mock(PropertyConfig)
@@ -75,7 +74,7 @@ class SimpleValueBinderSpec extends Specification {
         persistentPropertyToPropertyConfig.toPropertyConfig(prop) >> pc
         prop.getOwner() >> owner
         owner.getMappedForm() >> mapping
-        typeNameProvider.getTypeName(prop, mapping) >> null
+        prop.getTypeName(mapping) >> null
         pc.isDerived() >> false
         pc.getColumns() >> null
         prop.getType() >> Integer
@@ -94,7 +93,7 @@ class SimpleValueBinderSpec extends Specification {
 
     def "derived property adds no columns but adds formula, except TenantId"() 
{
         given:
-        def prop = Mock(PersistentProperty)
+        def prop = Mock(GrailsHibernatePersistentProperty)
         def tenantProp = Mock(TenantId)
         def owner = Mock(GrailsHibernatePersistentEntity)
         def mapping = Mock(Mapping)
@@ -108,7 +107,7 @@ class SimpleValueBinderSpec extends Specification {
         prop.getOwner() >> owner
         tenantProp.getOwner() >> owner
         owner.getMappedForm() >> mapping
-        typeNameProvider.getTypeName(_, _) >> 'X'
+        prop.getTypeName(_) >> 'X'
 
         pc.isDerived() >> true
         pc.getFormula() >> 'x+y'
@@ -135,7 +134,7 @@ class SimpleValueBinderSpec extends Specification {
 
     def "applies generator and maps sequence param to 
SequenceStyleGenerator.SEQUENCE_PARAM"() {
         given:
-        def prop = Mock(PersistentProperty)
+        def prop = Mock(GrailsHibernatePersistentProperty)
         def owner = Mock(GrailsHibernatePersistentEntity)
         def mapping = Mock(Mapping)
         def pc = Mock(PropertyConfig)
@@ -146,7 +145,7 @@ class SimpleValueBinderSpec extends Specification {
         persistentPropertyToPropertyConfig.toPropertyConfig(prop) >> pc
         prop.getOwner() >> owner
         owner.getMappedForm() >> mapping
-        typeNameProvider.getTypeName(prop, mapping) >> 'Y'
+        prop.getTypeName(mapping) >> 'Y'
         pc.isDerived() >> false
         pc.getColumns() >> null
         pc.getGenerator() >> 'sequence'
@@ -165,7 +164,7 @@ class SimpleValueBinderSpec extends Specification {
 
     def "binds for each provided column config and adds to table and simple 
value"() {
         given:
-        def prop = Mock(PersistentProperty)
+        def prop = Mock(GrailsHibernatePersistentProperty)
         def parent = Mock(PersistentProperty)
         def owner = Mock(GrailsHibernatePersistentEntity)
         def mapping = Mock(Mapping)
@@ -178,7 +177,7 @@ class SimpleValueBinderSpec extends Specification {
         persistentPropertyToPropertyConfig.toPropertyConfig(prop) >> pc
         prop.getOwner() >> owner
         owner.getMappedForm() >> mapping
-        typeNameProvider.getTypeName(prop, mapping) >> 'Z'
+        prop.getTypeName(mapping) >> 'Z'
         pc.isDerived() >> false
         pc.getColumns() >> [cc1, cc2]
         prop.isNullable() >> true
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
deleted file mode 100644
index c8dc778b88..0000000000
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/TypeNameProviderSpec.groovy
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.grails.orm.hibernate.cfg.domainbinding
-
-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
-import org.hibernate.usertype.BaseUserTypeSupport
-
-import java.util.function.BiConsumer
-
-class TypeNameProviderSpec extends HibernateGormDatastoreSpec {
-
-    void "Test - type not a class"() {
-        when:
-        def grailsDomainBinder = getGrailsDomainBinder()
-        def simpleName = "Book"
-        def fieldProperties = ["name": String]
-        def mappingProperties = ["name": "type: 'text'"]
-        def persistentEntity = createPersistentEntity(grailsDomainBinder, 
simpleName, fieldProperties, mappingProperties)
-        def property = persistentEntity.getPersistentProperties()[0]
-        Mapping mapping = new Mapping()
-        mapping.setUserTypes(["foo.Bar": persistentEntity.getJavaClass()])
-        def name = new TypeNameProvider().getTypeName(property , mapping)
-
-        then:
-        name == "text"
-
-    }
-
-    void "Test - type is a class"() {
-        when:
-        def grailsDomainBinder = getGrailsDomainBinder()
-        def simpleName = "Book"
-        def fieldProperties = ["name": String]
-        def mappingProperties = ["name": "type: String"]
-        def persistentEntity = createPersistentEntity(grailsDomainBinder, 
simpleName, fieldProperties, mappingProperties)
-        def property = persistentEntity.getPersistentProperties()[0]
-        Mapping mapping = new Mapping()
-        def name = new TypeNameProvider().getTypeName(property, mapping)
-
-        then:
-        name == "java.lang.String"
-
-    }
-
-    void "Test - type not included but in general mapping"() {
-        when:
-        def grailsDomainBinder = getGrailsDomainBinder()
-        def persistentEntity = 
getMappingContext().addPersistentEntity(Employee) as HibernatePersistentEntity
-        MappingCacheHolder.getInstance().cacheMapping(persistentEntity)
-        def property = persistentEntity.getPersistentProperties()[0]
-        Mapping mapping = new Mapping()
-        mapping.setUserTypes([(Salary): SalaryType])
-        PropertyConfig config = new 
PersistentPropertyToPropertyConfig().toPropertyConfig(property)
-        def name = new TypeNameProvider().getTypeName(property, mapping)
-
-        then:
-        name == SalaryType.name
-
-    }
-
-}
-
-class Salary {
-    BigDecimal amount
-}
-
-class SalaryType extends  BaseUserTypeSupport<Salary> {
-    @Override
-    protected void resolve(BiConsumer<BasicJavaType<Salary>, JdbcType> 
resolutionConsumer) {
-    }
-}
-@Entity
-class Employee {
-    Salary salary
-}
-
-
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java
index 4f6ca53da5..75c83e963f 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java
@@ -27,10 +27,10 @@ import org.grails.datastore.mapping.config.Entity;
  * @since 1.0
  */
 @SuppressWarnings("rawtypes")
-public abstract class AbstractClassMapping<T extends Entity> implements 
ClassMapping {
+public abstract class AbstractClassMapping<T extends Entity> implements 
ClassMapping<T> {
     protected PersistentEntity entity;
     protected MappingContext context;
-    private IdentityMapping identifierMapping;
+    private IdentityMapping<?> identifierMapping;
 
     public AbstractClassMapping(PersistentEntity entity, MappingContext 
context) {
         this.entity = entity;
@@ -45,7 +45,7 @@ public abstract class AbstractClassMapping<T extends Entity> 
implements ClassMap
 
     public abstract T getMappedForm();
 
-    public IdentityMapping getIdentifier() {
+    public IdentityMapping<?> getIdentifier() {
         return identifierMapping;
     }
 }
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java
index c14ef183b0..588a856aa1 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java
@@ -345,7 +345,7 @@ public abstract class AbstractPersistentEntity<T extends 
Entity> implements Pers
     }
 
     public ClassMapping<T> getMapping() {
-        return new AbstractClassMapping<Entity>(this, context) {
+        return (ClassMapping<T>) new AbstractClassMapping<Entity>(this, 
context) {
             @Override
             public Entity getMappedForm() {
                 return new Entity();
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java
index ee861e4638..468e740943 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java
@@ -47,5 +47,5 @@ public interface ClassMapping<T extends Entity> {
      *
      * @return The Identity
      */
-    IdentityMapping getIdentifier();
+    IdentityMapping<?> getIdentifier();
 }
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultIdentityMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultIdentityMapping.java
new file mode 100644
index 0000000000..93500759c0
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultIdentityMapping.java
@@ -0,0 +1,68 @@
+/*
+ *  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.datastore.mapping.model;
+
+import org.grails.datastore.mapping.config.Property;
+
+import static 
org.grails.datastore.mapping.model.MappingFactory.IDENTITY_PROPERTY;
+
+/**
+ * Default implementation of the {@link IdentityMapping} interface
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class DefaultIdentityMapping<T extends Property> extends 
DefaultPropertyMapping<T> implements IdentityMapping<T> {
+
+    private final String[] identifierNames;
+    private final ValueGenerator generator;
+
+    public DefaultIdentityMapping(ClassMapping classMapping, T mappedForm) {
+        this(classMapping, mappedForm, ValueGenerator.AUTO);
+    }
+
+    public DefaultIdentityMapping(ClassMapping classMapping, T mappedForm, 
ValueGenerator generator) {
+        super(classMapping, mappedForm);
+        this.generator = generator;
+        PersistentProperty identity = classMapping.getEntity().getIdentity();
+        String propertyName = identity != null ? 
identity.getMapping().getMappedForm().getName() : null;
+        if (propertyName != null) {
+            this.identifierNames = new String[] { propertyName };
+        }
+        else {
+            this.identifierNames = new String[] { IDENTITY_PROPERTY };
+        }
+    }
+
+    public DefaultIdentityMapping(ClassMapping classMapping, T mappedForm, 
String[] identifierNames, ValueGenerator generator) {
+        super(classMapping, mappedForm);
+        this.identifierNames = identifierNames;
+        this.generator = generator;
+    }
+
+    @Override
+    public String[] getIdentifierName() {
+        return identifierNames;
+    }
+
+    @Override
+    public ValueGenerator getGenerator() {
+        return generator;
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultPropertyMapping.java
similarity index 58%
copy from 
grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
copy to 
grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultPropertyMapping.java
index 14b9f65289..f1dd9bdd58 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DefaultPropertyMapping.java
@@ -18,24 +18,33 @@
  */
 package org.grails.datastore.mapping.model;
 
+import org.grails.datastore.mapping.config.Property;
+
 /**
+ * Default implementation of the {@link PropertyMapping} interface
+ *
+ * @param <T> The mapped form type
+ *
  * @author Graeme Rocher
  * @since 1.0
  */
-@SuppressWarnings("rawtypes")
-public interface IdentityMapping extends PropertyMapping {
+public class DefaultPropertyMapping<T extends Property> implements 
PropertyMapping<T> {
+
+    private final ClassMapping classMapping;
+    private final T mappedForm;
+
+    public DefaultPropertyMapping(ClassMapping classMapping, T mappedForm) {
+        this.classMapping = classMapping;
+        this.mappedForm = mappedForm;
+    }
 
-    /**
-     * The identifier property name(s). Usually there is just one identifier
-     * name, however in the case of a composite or natural identifier there
-     * may be serveral.
-     *
-     * @return identifier names that make up the key
-     */
-    String[] getIdentifierName();
+    @Override
+    public ClassMapping getClassMapping() {
+        return classMapping;
+    }
 
-    /**
-     * @return The type of value generated used
-     */
-    ValueGenerator getGenerator();
+    @Override
+    public T getMappedForm() {
+        return mappedForm;
+    }
 }
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
index 14b9f65289..04e3750120 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java
@@ -18,12 +18,13 @@
  */
 package org.grails.datastore.mapping.model;
 
+import org.grails.datastore.mapping.config.Property;
+
 /**
  * @author Graeme Rocher
  * @since 1.0
  */
-@SuppressWarnings("rawtypes")
-public interface IdentityMapping extends PropertyMapping {
+public interface IdentityMapping<T extends Property> extends 
PropertyMapping<T> {
 
     /**
      * The identifier property name(s). Usually there is just one identifier
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java
index 9fd9754a34..ff4023ebad 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java
@@ -48,6 +48,18 @@ import org.grails.datastore.mapping.config.Entity;
 import org.grails.datastore.mapping.config.Property;
 import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller;
 import org.grails.datastore.mapping.model.config.GormProperties;
+import org.grails.datastore.mapping.model.types.mapping.BasicWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.CustomWithMapping;
+import 
org.grails.datastore.mapping.model.types.mapping.EmbeddedCollectionWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.EmbeddedWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.IdentityWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.ManyToManyWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.ManyToOneWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.OneToManyWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.OneToOneWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.SimpleWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.TenantIdWithMapping;
+import org.grails.datastore.mapping.model.types.mapping.PropertyWithMapping;
 import org.grails.datastore.mapping.model.types.Association;
 import org.grails.datastore.mapping.model.types.Basic;
 import org.grails.datastore.mapping.model.types.Custom;
@@ -196,13 +208,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return An Identity instance
      */
     public Identity<T> createIdentity(PersistentEntity owner, MappingContext 
context, PropertyDescriptor pd) {
-        return new Identity<>(owner, context, pd) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping<T> getMapping() {
-                return propertyMapping;
-            }
-        };
+        IdentityWithMapping<T> identity = new IdentityWithMapping<>(owner, 
context, pd);
+        identity.setMapping(createPropertyMapping(identity, owner));
+        return identity;
     }
 
     /**
@@ -214,13 +222,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return An Identity instance
      */
     public TenantId<T> createTenantId(PersistentEntity owner, MappingContext 
context, PropertyDescriptor pd) {
-        return new TenantId<>(owner, context, pd) {
-            PropertyMapping<T> propertyMapping = 
createDerivedPropertyMapping(this, owner);
-
-            public PropertyMapping<T> getMapping() {
-                return propertyMapping;
-            }
-        };
+        TenantIdWithMapping<T> tenantId = new TenantIdWithMapping<>(owner, 
context, pd);
+        tenantId.setMapping(createDerivedPropertyMapping(tenantId, owner));
+        return tenantId;
     }
 
     /**
@@ -251,13 +255,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
         if (customTypeMarshaller == null && !allowArbitraryCustomTypes()) {
             throw new IllegalStateException("Cannot create a custom type 
without a type converter for type " + propertyType);
         }
-        return new Custom<>(owner, context, pd, customTypeMarshaller) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping<T> getMapping() {
-                return propertyMapping;
-            }
-        };
+        CustomWithMapping<T> custom = new CustomWithMapping<>(owner, context, 
pd, customTypeMarshaller);
+        custom.setMapping(createPropertyMapping(custom, owner));
+        return custom;
     }
 
     protected boolean allowArbitraryCustomTypes() {
@@ -295,43 +295,19 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return A Simple property type
      */
     public Simple<T> createSimple(PersistentEntity owner, MappingContext 
context, PropertyDescriptor pd) {
-        return new Simple<>(owner, context, pd) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping<T> getMapping() {
-                return propertyMapping;
-            }
-        };
+        SimpleWithMapping<T> simple = new SimpleWithMapping<>(owner, context, 
pd);
+        simple.setMapping(createPropertyMapping(simple, owner));
+        return simple;
     }
 
     protected PropertyMapping<T> createPropertyMapping(final 
PersistentProperty<T> property, final PersistentEntity owner) {
-        return new PropertyMapping<>() {
-            private T mappedForm = createMappedForm(property);
-
-            public ClassMapping getClassMapping() {
-                return owner.getMapping();
-            }
-
-            public T getMappedForm() {
-                return mappedForm;
-            }
-        };
+        return new DefaultPropertyMapping<>(owner.getMapping(), 
createMappedForm(property));
     }
 
-    private PropertyMapping<T> createDerivedPropertyMapping(final 
PersistentProperty<T> property, final PersistentEntity owner) {
+    protected PropertyMapping<T> createDerivedPropertyMapping(final 
PersistentProperty<T> property, final PersistentEntity owner) {
         final T mappedFormObject = createMappedForm(property);
         mappedFormObject.setDerived(true);
-        return new PropertyMapping<>() {
-            private T mappedForm = mappedFormObject;
-
-            public ClassMapping getClassMapping() {
-                return owner.getMapping();
-            }
-
-            public T getMappedForm() {
-                return mappedForm;
-            }
-        };
+        return new DefaultPropertyMapping<>(owner.getMapping(), 
mappedFormObject);
     }
 
     /**
@@ -343,18 +319,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return The ToOne instance
      */
     public ToOne createOneToOne(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
-        return new OneToOne<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("one-to-one: ", this);
-            }
-        };
+        OneToOneWithMapping<T> oneToOne = new OneToOneWithMapping<>(entity, 
context, property);
+        oneToOne.setMapping(createPropertyMapping(oneToOne, entity));
+        return oneToOne;
     }
 
     /**
@@ -366,19 +333,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return The ToOne instance
      */
     public ToOne createManyToOne(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
-        return new ManyToOne<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("many-to-one: ", this);
-            }
-
-        };
-
+        ManyToOneWithMapping<T> manyToOne = new ManyToOneWithMapping<>(entity, 
context, property);
+        manyToOne.setMapping(createPropertyMapping(manyToOne, entity));
+        return manyToOne;
     }
 
     /**
@@ -390,18 +347,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return The {@link OneToMany} instance
      */
     public OneToMany createOneToMany(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
-        return new OneToMany<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("one-to-many: ", this);
-            }
-        };
-
+        OneToManyWithMapping<T> oneToMany = new OneToManyWithMapping<>(entity, 
context, property);
+        oneToMany.setMapping(createPropertyMapping(oneToMany, entity));
+        return oneToMany;
     }
 
     /**
@@ -413,18 +361,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      * @return The {@link ManyToMany} instance
      */
     public ManyToMany createManyToMany(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
-        return new ManyToMany<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("many-to-many: ", this);
-            }
-        };
+        ManyToManyWithMapping<T> manyToMany = new 
ManyToManyWithMapping<>(entity, context, property);
+        manyToMany.setMapping(createPropertyMapping(manyToMany, entity));
+        return manyToMany;
     }
 
     /**
@@ -437,18 +376,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      */
     public Embedded createEmbedded(PersistentEntity entity,
             MappingContext context, PropertyDescriptor property) {
-        return new Embedded<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("embedded: ", this);
-            }
-        };
+        EmbeddedWithMapping<T> embedded = new EmbeddedWithMapping<>(entity, 
context, property);
+        embedded.setMapping(createPropertyMapping(embedded, entity));
+        return embedded;
     }
 
     /**
@@ -461,18 +391,9 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      */
     public EmbeddedCollection createEmbeddedCollection(PersistentEntity entity,
             MappingContext context, PropertyDescriptor property) {
-        return new EmbeddedCollection<T>(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-
-            @Override
-            public String toString() {
-                return associationtoString("embedded: ", this);
-            }
-        };
+        EmbeddedCollectionWithMapping<T> embedded = new 
EmbeddedCollectionWithMapping<>(entity, context, property);
+        embedded.setMapping(createPropertyMapping(embedded, entity));
+        return embedded;
     }
 
     /**
@@ -485,13 +406,8 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
      */
     public Basic createBasicCollection(PersistentEntity entity,
             MappingContext context, PropertyDescriptor property, Class 
collectionType) {
-        Basic basic = new Basic(entity, context, property) {
-            PropertyMapping<T> propertyMapping = createPropertyMapping(this, 
owner);
-
-            public PropertyMapping getMapping() {
-                return propertyMapping;
-            }
-        };
+        BasicWithMapping<T> basic = new BasicWithMapping<>(entity, context, 
property);
+        basic.setMapping(createPropertyMapping(basic, entity));
 
         CustomTypeMarshaller customTypeMarshaller = findCustomType(context, 
property.getPropertyType());
 
@@ -533,61 +449,15 @@ public abstract class MappingFactory<R extends Entity, T 
extends Property> {
     }
 
     public IdentityMapping createDefaultIdentityMapping(final ClassMapping 
classMapping) {
-        return new IdentityMapping() {
-
-            public String[] getIdentifierName() {
-                PersistentProperty identity = 
classMapping.getEntity().getIdentity();
-                String propertyName = identity != null ? 
identity.getMapping().getMappedForm().getName() : null;
-                if (propertyName != null) {
-                    return new String[] { propertyName };
-                }
-                else {
-                    return new String[] { IDENTITY_PROPERTY };
-                }
-            }
-
-            @Override
-            public ValueGenerator getGenerator() {
-                return ValueGenerator.AUTO;
-            }
-
-            public ClassMapping getClassMapping() {
-                return classMapping;
-            }
-
-            public Property getMappedForm() {
-                return 
classMapping.getEntity().getIdentity().getMapping().getMappedForm();
-            }
-        };
+        return new DefaultIdentityMapping(classMapping, 
classMapping.getEntity().getIdentity().getMapping().getMappedForm());
     }
 
     protected IdentityMapping createDefaultIdentityMapping(final ClassMapping 
classMapping, final T property) {
-        final String targetName = property != null ? property.getName() : null;
-        final String generator = property != null ? property.getGenerator() : 
null;
-        return new IdentityMapping() {
-
-            public String[] getIdentifierName() {
-                if (targetName != null) {
-                    return new String[] { targetName };
-                }
-                else {
-                    return new String[] { IDENTITY_PROPERTY };
-                }
-            }
-
-            @Override
-            public ValueGenerator getGenerator() {
-                return generator != null ? ValueGenerator.valueOf(generator) : 
ValueGenerator.AUTO;
-            }
-
-            public ClassMapping getClassMapping() {
-                return classMapping;
-            }
-
-            public Property getMappedForm() {
-                return property;
-            }
-        };
+        String targetName = property != null ? property.getName() : null;
+        String[] identifierNames = targetName != null ? new String[] { 
targetName } : new String[] { IDENTITY_PROPERTY };
+        String generatorName = property != null ? property.getGenerator() : 
null;
+        ValueGenerator generator = generatorName != null ? 
ValueGenerator.valueOf(generatorName) : ValueGenerator.AUTO;
+        return new DefaultIdentityMapping<>(classMapping, property, 
identifierNames, generator);
     }
 
     public static String associationtoString(String desc, Association a) {
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java
index e9a1d87dcc..e06769b0fc 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java
@@ -66,7 +66,7 @@ public interface PersistentProperty<T extends Property> {
     */
     PropertyMapping<T> getMapping();
 
-    default T getMappedForm() {
+    default T  getMappedForm() {
         return Optional.of(getMapping())
                 .map(PropertyMapping::getMappedForm)
                 .orElse(null);
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java
index 1babfddf73..a25a1560c8 100644
--- 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java
@@ -21,6 +21,7 @@ package org.grails.datastore.mapping.model.types;
 
 import java.beans.PropertyDescriptor;
 
+import org.grails.datastore.mapping.config.Property;
 import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller;
 import org.grails.datastore.mapping.model.AbstractPersistentProperty;
 import org.grails.datastore.mapping.model.MappingContext;
@@ -32,7 +33,7 @@ import org.grails.datastore.mapping.model.PersistentEntity;
  * @author Graeme Rocher
  * @since 1.0
  */
-public abstract class Custom<T> extends AbstractPersistentProperty {
+public abstract class Custom<T extends Property> extends 
AbstractPersistentProperty<T> {
     private CustomTypeMarshaller<?, ?, ?> customTypeMarshaller;
 
     public Custom(PersistentEntity owner, MappingContext context, 
PropertyDescriptor descriptor,
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/BasicWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/BasicWithMapping.java
new file mode 100644
index 0000000000..fc6535b3d9
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/BasicWithMapping.java
@@ -0,0 +1,58 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.Basic;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.Basic} property with a 
{@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class BasicWithMapping<T extends Property> extends Basic<T> implements 
PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public BasicWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public BasicWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+}
\ No newline at end of file
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/CustomWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/CustomWithMapping.java
new file mode 100644
index 0000000000..f6f5014e11
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/CustomWithMapping.java
@@ -0,0 +1,59 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.Custom;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.Custom} property with a 
{@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class CustomWithMapping<T extends Property> extends Custom<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public CustomWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property, CustomTypeMarshaller<?, ?, ?> 
customTypeMarshaller) {
+        super(entity, context, property, customTypeMarshaller);
+    }
+
+    public CustomWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property, CustomTypeMarshaller<?, ?, ?> 
customTypeMarshaller, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property, customTypeMarshaller);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedCollectionWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedCollectionWithMapping.java
new file mode 100644
index 0000000000..787ed0f80d
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedCollectionWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.EmbeddedCollection;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * An {@link org.grails.datastore.mapping.model.types.EmbeddedCollection} 
property with a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class EmbeddedCollectionWithMapping<T extends Property> extends 
EmbeddedCollection<T> implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public EmbeddedCollectionWithMapping(PersistentEntity entity, 
MappingContext context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public EmbeddedCollectionWithMapping(PersistentEntity entity, 
MappingContext context, PropertyDescriptor property, PropertyMapping<T> 
propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("embedded: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedWithMapping.java
new file mode 100644
index 0000000000..e0cf1df421
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/EmbeddedWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.Embedded;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * An {@link org.grails.datastore.mapping.model.types.Embedded} property with 
a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class EmbeddedWithMapping<T extends Property> extends Embedded<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public EmbeddedWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public EmbeddedWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("embedded: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/IdentityWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/IdentityWithMapping.java
new file mode 100644
index 0000000000..de3a6aa2a7
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/IdentityWithMapping.java
@@ -0,0 +1,58 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.Identity;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * An {@link org.grails.datastore.mapping.model.types.Identity} property with 
a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class IdentityWithMapping<T extends Property> extends Identity<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public IdentityWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public IdentityWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToManyWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToManyWithMapping.java
new file mode 100644
index 0000000000..ad83011fb3
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToManyWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.ManyToMany;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.ManyToMany} property with 
a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class ManyToManyWithMapping<T extends Property> extends ManyToMany<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public ManyToManyWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public ManyToManyWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("many-to-many: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToOneWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToOneWithMapping.java
new file mode 100644
index 0000000000..432728810f
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/ManyToOneWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.ManyToOne;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.ManyToOne} property with 
a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class ManyToOneWithMapping<T extends Property> extends ManyToOne<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public ManyToOneWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public ManyToOneWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("many-to-one: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToManyWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToManyWithMapping.java
new file mode 100644
index 0000000000..32f1b6f08f
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToManyWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.OneToMany;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.OneToMany} property with 
a {@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class OneToManyWithMapping<T extends Property> extends OneToMany<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public OneToManyWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public OneToManyWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("one-to-many: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToOneWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToOneWithMapping.java
new file mode 100644
index 0000000000..197cac43b1
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/OneToOneWithMapping.java
@@ -0,0 +1,64 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.MappingFactory;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.OneToOne;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.OneToOne} property with a 
{@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class OneToOneWithMapping<T extends Property> extends OneToOne<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public OneToOneWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public OneToOneWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public String toString() {
+        return MappingFactory.associationtoString("one-to-one: ", this);
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/PropertyWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/PropertyWithMapping.java
new file mode 100644
index 0000000000..df15246a8b
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/PropertyWithMapping.java
@@ -0,0 +1,10 @@
+package org.grails.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.PersistentProperty;
+import org.grails.datastore.mapping.model.PropertyMapping;
+
+public interface PropertyWithMapping<T extends Property> extends 
PersistentProperty<T> {
+
+    PropertyMapping<T> getMapping();
+}
\ No newline at end of file
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/SimpleWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/SimpleWithMapping.java
new file mode 100644
index 0000000000..d3e7dd99d2
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/SimpleWithMapping.java
@@ -0,0 +1,58 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.Simple;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.Simple} property with a 
{@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class SimpleWithMapping<T extends Property> extends Simple<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public SimpleWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public SimpleWithMapping(PersistentEntity entity, MappingContext context, 
PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+}
diff --git 
a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/TenantIdWithMapping.java
 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/TenantIdWithMapping.java
new file mode 100644
index 0000000000..837e67bd2e
--- /dev/null
+++ 
b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/mapping/TenantIdWithMapping.java
@@ -0,0 +1,58 @@
+/*
+ *  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.datastore.mapping.model.types.mapping;
+
+import org.grails.datastore.mapping.config.Property;
+import org.grails.datastore.mapping.model.MappingContext;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PropertyMapping;
+import org.grails.datastore.mapping.model.types.TenantId;
+
+import java.beans.PropertyDescriptor;
+
+/**
+ * A {@link org.grails.datastore.mapping.model.types.TenantId} property with a 
{@link org.grails.datastore.mapping.model.PropertyMapping}
+ *
+ * @param <T> The property type
+ *
+ * @author Graeme Rocher
+ * @since 1.0
+ */
+public class TenantIdWithMapping<T extends Property> extends TenantId<T> 
implements PropertyWithMapping<T> {
+
+    protected PropertyMapping<T> propertyMapping;
+
+    public TenantIdWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property) {
+        super(entity, context, property);
+    }
+
+    public TenantIdWithMapping(PersistentEntity entity, MappingContext 
context, PropertyDescriptor property, PropertyMapping<T> propertyMapping) {
+        super(entity, context, property);
+        this.propertyMapping = propertyMapping;
+    }
+
+    @Override
+    public PropertyMapping<T> getMapping() {
+        return propertyMapping;
+    }
+
+    public void setMapping(PropertyMapping<T> propertyMapping) {
+        this.propertyMapping = propertyMapping;
+    }
+}

Reply via email to