jamesfredley commented on code in PR #16695:
URL: https://github.com/apache/grails-core/pull/16695#discussion_r4339129900


##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentProperty.java:
##########
@@ -114,23 +123,43 @@ default GrailsHibernatePersistentEntity 
getHibernateOwner() {
         return (GrailsHibernatePersistentEntity) getOwner();
     }
 
-    @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
     default Class<?> getUserType() {
         PropertyConfig config = getMappedForm();
         if (config == null) return null;
         Object typeObj = config.getType();
-        Class<?> userType = null;
-        if (typeObj instanceof Class<?>) {
-            userType = (Class<?>) typeObj;
-        } else if (typeObj != null) {
-            String typeName = typeObj.toString();
-            try {
-                userType = Class.forName(typeName, true, 
Thread.currentThread().getContextClassLoader());
-            } catch (ClassNotFoundException ignored) {
-                // ignore
-            }
+        if (typeObj instanceof Class<?> userType) {
+            return userType;
+        }
+        return typeObj == null ? null : classForName(typeObj.toString());
+    }
+
+    /**
+     * The {@link CompositeUserType} the property is mapped with: the {@code 
type} of its own mapping, or
+     * the {@code user-type} registered for its class in the mapping of its 
owner, when that class
+     * implements the interface. A composite user type spans one column per 
attribute of its
+     * {@linkplain CompositeUserType#embeddable() embeddable class} and is 
bound as a component.
+     *
+     * @return The composite user type, or {@code null} when the property is 
not mapped with one
+     */
+    @SuppressWarnings("unchecked")
+    default @Nullable Class<? extends CompositeUserType<?>> 
getCompositeUserType() {
+        Class<?> userType = getUserType();
+        if (userType == null) {
+            userType = getRegisteredUserType();

Review Comment:
   This fallback runs whenever `getUserType()` returns null, and 
`getUserType()` returns null for a Hibernate alias such as `serializable` 
because that string is not a class name. A value class that has a registered 
composite user type, with an explicit `amount type: 'serializable'`, is 
therefore bound as a multi-column component instead of one serialized column. 
That changes the schema and can break an existing database. It also contradicts 
the documented per-property precedence.
   
   Consult the registered type only when the property mapping has no explicit 
`type`. Please add a datastore-backed regression: a global composite 
registration plus a per-property `serializable` override, asserting one basic 
column and a successful round-trip.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to