Description
There has been a fix in versions 2.7.0 and higher for parameter typing which is causing issues in JPA queries when using converters. #2370
This fix was made to help native queries handle null parameters but is also affecting JPA queries. In our situation we are using a converter to transform boolean values to chars eg. 'Y' or 'N'. When using these values, the data type binding is set as AttributeConverterTypeAdapter. This binding type is generated by @convert annotation in the entity class declaration and we want to keep it that way even in null cases. With the fix previously mentioned, in null cases this data type binding is overwritten by the parameter type.
The entity mapping with @convert annotation is the following:
@Column(name = "is_deleted")
@Convert(converter = BooleanCharConverter.class)
private boolean deleted;
And here is our JPA query:
@Query("SELECT DISTINCT pkg FROM Package pkg " +
"WHERE (pkg.deleted = :deleted OR :deleted IS NULL)")
List<Package> findPackages(@Param("deleted") Boolean deleted);
The change in null value handling breaks our implementation and the JPA queries end up with the following error:
ERROR: operator does not exist: character = boolean
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Position: 802
The binding works in the following way in hibernate:
public QueryImplementor setParameter(String name, Object value) {
getProducer().checkOpen();
if ( value instanceof TypedParameterValue ) {
final TypedParameterValue typedValueWrapper = (TypedParameterValue) value;
setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() );
}
else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) {
setParameterList( name, (Collection) value );
}
else {
getQueryParameterBindings().getBinding( name ).setBindValue( value );
}
return this;
}
If the value is an instance of TypedParameterValue, the parameter bind type is overwritten by the TypedParameterValue type. Previously null values were just bound without altering the binding type. Either this needs to be reverted for JPA queries or TypedParameterValue needs to fetch the parameter type from the ParameterMetadata where the data type generated by @convert annotation is stored.