Running a spring boot app which I recently updated from version 3.2.0
to 3.3.5
which updated Hibernate from version 6.3.1
to 6.5.3
.
I have DB procedure (PostgreSQL)
create procedure some_procedure(IN data some_custom_db_type[])
custom type
create type some_custom_db_type as
(
email text,
id bigint
);
Then in the app I have a JpaRepository
with this method
@Procedure(procedureName = "some_procedure")
void callSomeProcedure(SomeCustomDbType[] data);
record
public record SomeCustomDbType(String email, Long id) implements Serializable {
}
custom UserType
public class SomeCustomDbTypeDefinition implements UserType<SomeCustomDbType[]> {
public static final String TYPE_NAME = "some_custom_db_type";
public static final SomeCustomDbTypeDefinition INSTANCE = new SomeCustomDbTypeDefinition();
@Override
public int getSqlType() {
return SqlTypes.ARRAY;
}
@Override
public Class<SomeCustomDbType[]> returnedClass() {
return SomeCustomDbType[].class;
}
...
custom type registration
public class CustomPostgresqlTypes implements TypeContributor {
@Override
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType(SomeCustomDbTypeDefinition.INSTANCE);
}
}
and registration of CustomPostgresqlTypes
in META-INF/services/org.hibernate.boot.model.TypeContributor
This approach worked just fine in version 6.3.1
but stopped working in version 6.5.3
.
I tried to find what changed and found out there were some changes on BasicTypeRegistry
class. Here’s a diff which causes the problem:
Tried to find the type using the the old approach
getRegisteredType( javaType.getName() );
instead of the new one
getRegisteredType( javaType.getTypeName() );
and it was found just fine.
Basically when the custom type is not found, the parameter is registered as a basic type and an exception is thrown
java.lang.ClassCastException: class [Lcom.db.custom.SomeCustomDbType; cannot be cast to class [B ([Lcom.db.custom.SomeCustomDbType; is in unnamed module of loader 'app'; [B is in module java.base of loader 'bootstrap')
at org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType$1.doBind(VarbinaryJdbcType.java:100)
at org.hibernate.type.descriptor.jdbc.BasicBinder.bind(BasicBinder.java:61)
at org.hibernate.sql.exec.internal.AbstractJdbcParameter.bindParameterValue(AbstractJdbcParameter.java:130)
at org.hibernate.sql.exec.internal.AbstractJdbcParameter.bindParameterValue(AbstractJdbcParameter.java:101)
at org.hibernate.procedure.internal.ProcedureCallImpl.buildOutputs(ProcedureCallImpl.java:702)
Is there a problem with my approach in the first place so I was lucky it worked in the old version or is there some problem with the new one?