diff --git a/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java index da28a007abc..9a6f78f5970 100644 --- a/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -1368,11 +1368,11 @@ public static Mapping getMapping(Class theClass) { public static Mapping getMapping(GrailsDomainClass domainClass) { return domainClass == null ? null : MAPPING_CACHE.get(domainClass.getClazz()); } - + public static void clearMappingCache() { MAPPING_CACHE.clear(); } - + public static void clearMappingCache(Class theClass) { String className = theClass.getName(); for(Iterator, Mapping>> it = MAPPING_CACHE.entrySet().iterator(); it.hasNext();) { @@ -1807,7 +1807,14 @@ protected static void createClassProperties(GrailsDomainClass domainClass, Persi Class userType = getUserType(currentGrailsProp); - if (collectionType != null) { + if (userType != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); + } + value = new SimpleValue(mappings, table); + bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, EMPTY_PATH, mappings, sessionFactoryBeanName); + } + else if (collectionType != null) { String typeName = getTypeName(currentGrailsProp, getPropertyConfig(currentGrailsProp),gormMapping); if ("serializable".equals(typeName)) { value = new SimpleValue(mappings, table); diff --git a/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomUserTypeOverridesGrailsMapMappingTests.groovy b/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomUserTypeOverridesGrailsMapMappingTests.groovy new file mode 100644 index 00000000000..6c14ce5da6e --- /dev/null +++ b/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/CustomUserTypeOverridesGrailsMapMappingTests.groovy @@ -0,0 +1,38 @@ +package org.codehaus.groovy.grails.orm.hibernate + +import grails.persistence.Entity + +import org.codehaus.groovy.grails.orm.hibernate.cfg.MapFakeUserType + +class CustomUserTypeOverridesGrailsMapMappingTests extends AbstractGrailsHibernateTests { + + void testUserTypeOverridesGrailsMapMappingTests() { + def d = new DomainUserTypeMappings() + + d.myMap = [foo:"bar"] + + assert d.save(flush:true) != null + + // the map should not be mapped onto a join table but instead a single column + session.connection().prepareStatement("select my_map from domain_user_type_mappings").execute() + + session.clear() + + d = DomainUserTypeMappings.get(d.id) + + assert d != null + } + + @Override protected getDomainClasses() { + [DomainUserTypeMappings] + } +} + +@Entity +class DomainUserTypeMappings { + Map myMap + + static mapping = { + myMap type:MapFakeUserType + } +} diff --git a/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/MapFakeUserType.groovy b/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/MapFakeUserType.groovy new file mode 100644 index 00000000000..e0a3cc914e9 --- /dev/null +++ b/grails-test-suite-persistence/src/test/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/MapFakeUserType.groovy @@ -0,0 +1,60 @@ +package org.codehaus.groovy.grails.orm.hibernate.cfg + +import java.io.Serializable +import java.sql.PreparedStatement +import java.sql.ResultSet +import java.sql.SQLException +import java.sql.Types +import java.util.HashMap +import java.util.Map + +import org.hibernate.HibernateException +import org.hibernate.usertype.UserType + +public class MapFakeUserType implements UserType { + + int[] sqlTypes() { Types.VARCHAR } + Class returnedClass() { MapFakeUserType } + + public Object nullSafeGet(ResultSet rs, String[] names, owner) throws SQLException { + String name = rs.getString(names[0]) + rs.wasNull() ? null : new MapFakeUserType(name: name) + } + + public void nullSafeSet(PreparedStatement ps, value, int index) throws SQLException { + if (value == null) { + ps.setNull(index, Types.VARCHAR) + } + else { + ps.setString(index, value.name) + } + } + + public boolean equals(Object x, Object y) throws HibernateException { + return x == y; + } + + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + public boolean isMutable() { + return false; + } + + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable)value; + } + + public Object assemble(Serializable cached, Object owner) throws HibernateException { + return cached; + } + + public Object replace(Object original, Object target, Object owner) throws HibernateException { + return original; + } +}