This is probably the weirdest error I've seen on hibernate in my life
I've a spring-boot project
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
I need to lookup later what exact versions of hibernate and jpa this starter is using...
The problem is: I've a custom function in my database as follows
CREATE OR REPLACE FUNCTION IS_EXTRA_MATCH(addressExtra text, containedValue text)
returns boolean
language plpgsql
LEAKPROOF
CALLED ON NULL INPUT
PARALLEL SAFE
The code of the function itself is irrelevant, it works, and I've tested with a range of inputs, nulls, empty string... etc etc etc etc
The function works, no unexpected results occur
Then I've a custom query on my jpa repository which uses this function
@Query("SELECT a FROM address a WHERE a.zipcode = :zipcode AND a.number = :num AND CAST(IS_EXTRA_MATCH(a.extra, :extra) AS java.lang.Boolean) = true")
Set<AddressEntity> findByZipcodeAndNumberAndExtra(@Param("zipcode") String zipcode, @Param("num") int num, @Param("extra") String extra);
The first thing that bothers me is that if I remove '= true' from end of query it won't work... so even when I cast the element to boolean, Hibernate doesn't know how to evaluate it without something to compare... but this is not the problem
The problem is WHEN :extra
is null, the query crashes with the error
2022-08-12 00:52:19.529 ERROR 1 --- [io-10000-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
org.postgresql.util.PSQLException: ERROR: function is_extra_match(character varying, bytea) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 624
The whole stacktrace is giant and as I've read it, irrelevant... what this is saying that somehow Hibernate converts the null string into a bytea and the function can't deal with that.
I've tried to force a cast CAST(:extra as text)
but it won't work
Is there any way to tell Hibernate to use NULL AS NULL and not as this weird data type?
Please if you read that far don't come with the suggestion
why don't you check for null before calling the function...
If anyone knows the proper way to handle this problem please help me
CodePudding user response:
I've tried to force a cast CAST(:extra as text) but it won't work
Maybe tell us what it is that doesn't work? For one, you should be using cast(:extra as String)
as the cast target types for JPQL/HQL are domain model basic types and not database specific types. Share stack traces or SQL that is generated which doesn't work.
The problem here really is the JDBC driver and inability to infer a parameter type in combination with Spring Data being unable to pass parameter values in a typed fashion when values are null. Hibernate can't infer the type of the parameter, because it doesn't know the second parameter of IS_EXTRA_MATCH
is String
/text
. So it tries to infer the type based on the value you pass. Since you pass null
, Hibernate will default to some JDBC methods like setBytes
to set the value.
The answer Hibernate has for this, is the TypedParameterValue
class, which you can use to pass typed parameter values.