diff --git a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java index 9ebeb90a9e..d02a4b2e4f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/CustomType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/CustomType.java @@ -191,22 +191,36 @@ public class CustomType @Override public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner) { - return (Serializable) disassemble( value, session ); + return disassembleForCache( value ); } @Override public Serializable disassemble(Object value, SessionFactoryImplementor sessionFactory) throws HibernateException { - return (Serializable) disassemble( value, (SharedSessionContractImplementor) null ); + return disassembleForCache( value ); } - @Override - public Object disassemble(Object value, SharedSessionContractImplementor session) { + private Serializable disassembleForCache(Object value) { final Serializable disassembled = getUserType().disassemble( (J) value ); // Since UserType#disassemble is an optional operation, // we have to handle the fact that it could produce a null value, // in which case we will try to use a converter for disassembling, // or if that doesn't exist, simply use the domain value as is if ( disassembled == null && value != null ) { + final BasicValueConverter valueConverter = getUserType().getValueConverter(); + if ( valueConverter == null ) { + return disassembled; + } + else { + return (Serializable) valueConverter.toRelationalValue( (J) value ); + } + } + return disassembled; + } + + @Override + public Object disassemble(Object value, SharedSessionContractImplementor session) { + // Use the value converter if available for conversion to the jdbc representation + if ( value != null ) { final BasicValueConverter valueConverter = getUserType().getValueConverter(); if ( valueConverter == null ) { return value; @@ -215,7 +229,7 @@ public class CustomType return valueConverter.toRelationalValue( (J) value ); } } - return disassembled; + return value; } @Override diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/ContributedUserTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/ContributedUserTypeTest.java index 6e0f6e0614..eacb7134bc 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/ContributedUserTypeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/ContributedUserTypeTest.java @@ -40,7 +40,19 @@ public class ContributedUserTypeTest { Assertions.assertTrue( type instanceof CustomType, "Type was initialized too early i.e. before type-contributors were run" ); } - @Entity + @Test + @JiraKey( "HHH-17100" ) + public void testParameter(SessionFactoryScope scope) { + scope.inSession( + session -> { + session.createSelectionQuery( "from StringWrapperTestEntity e where e.stringWrapper = :p" ) + .setParameter( "p", new StringWrapper( "abc" ) ) + .getResultList(); + } + ); + } + + @Entity(name = "StringWrapperTestEntity") public static class StringWrapperTestEntity implements Serializable { @Id private Integer id; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/StringWrapperUserType.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/StringWrapperUserType.java index 957dfa30ae..772e726853 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/StringWrapperUserType.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/contributor/usertype/StringWrapperUserType.java @@ -96,13 +96,13 @@ public class StringWrapperUserType implements UserType { @Override public Serializable disassemble(StringWrapper value) throws HibernateException { - return deepCopy( value ); + return value == null ? null : value.getValue().getBytes(); } @Override public StringWrapper assemble(Serializable cached, Object owner) throws HibernateException { - return deepCopy( (StringWrapper) cached ); + return new StringWrapper( new String( (byte[]) cached ) ); } @Override