-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
After Upgrading to spring boot 2.7.5 from 2.7.4, we can see that the NULL query parameters which involves "LIKE" clause are getting bound as empty strings and not as NULL. The same is bound as NULL, if the query condition is "=".
Looks like the problem is due to usage of newer spring-data-jpa version (2.7.5) in spring boot 2.7.5.
Spring boot 2.7.4 was using spring-data-jpa version -2.7.3 where everything looks fine.
For example
If the query is as below and the p_user_name is passed as NULL,
select user from User where :p_user_name is null or userName = :p_user_name
the parameter is properly getting bound as NULL ->
binding parameter [1] as [VARCHAR] - [null]
binding parameter [2] as [VARCHAR] - [null]
Whereas if the query is changed to like below
select user from User where :p_user_name is null or userName LIKE :p_user_name
the parameter is incorrectly getting bound as EMPTY Strings->
binding parameter [1] as [VARCHAR] - []
binding parameter [2] as [VARCHAR] - []
This is failing the existing functionalities in the application.
There seems to be some changes to StringQuery$LikeParameterBinding class (prepare method).
spring-data-jpa.2.7.3 is straight forward:
@Nullable
@Override
public Object prepare(@Nullable Object value) {
if (value == null) {
return null;
}
switch (type) {
case STARTING_WITH:
return String.format("%s%%", value);
case ENDING_WITH:
return String.format("%%%s", value);
case CONTAINING:
return String.format("%%%s%%", value);
case LIKE:
default:
return value;
}
}
from spring-data-jpa-2.7.4 it uses PersistenceProvider.condense method
@Nullable
@Override
public Object prepare(@Nullable Object value) {
if (value == null) {
return null;
}
switch (type) {
case STARTING_WITH:
return String.format("%s%%", PersistenceProvider.condense(value));
case ENDING_WITH:
return String.format("%%%s", PersistenceProvider.condense(value));
case CONTAINING:
return String.format("%%%s%%", PersistenceProvider.condense(value));
case LIKE:
default:
return PersistenceProvider.condense(value);
}
}
This Persistence Provider is returning empty string for some reason when the parameter value is NULL.
public static Object condense(Object value) {
ClassLoader classLoader = PersistenceProvider.class.getClassLoader();
if (ClassUtils.isPresent("org.hibernate.jpa.TypedParameterValue", classLoader)) {
try {
Class<?> typeParameterValue = ClassUtils.forName("org.hibernate.jpa.TypedParameterValue", classLoader);
if (typeParameterValue.isInstance(value)) {
return "";
}
} catch (ClassNotFoundException | LinkageError o_O) {
return value;
}
}
return value;
}
It might not have been a problem if it is just changing the parameter at the LIKE position, But as the same named parameter is used else where, the parameter value is bound as EMPTY string at all places which is creating the problem.