1

I've a complex HQL query which I want to run. One of my params is a Set<Integer> with valid values for the result

something like: select * from table t where t.code IN (Set<Integer>)

This is very simple right? the problem is that I want this query to return ALL ITEMS, case the Set<Integer> is empty or null (don't need to be empty or null, working either case is enough)

considering the JPA repository method:

public Page<Table> findAll(@Param("codes") Set<Integer> codes);

i've tried several approaches:

SELECT t FROM table t where :codes IS NULL OR t.code IN (:codes)

runtime error: SQL Error: 1241, SQLState: 21000 (conn=3123) Operand should contain 1 column(s)

SELECT t FROM table t where (:codes) IS EMPTY OR t.code IN (:codes)

spring wont even boot up ??? is not mapped

SELECT t FROM table t where size((:codes)) = 0 OR t.code IN (:codes)

and many others

Is there a generic way to make this check and make this query to work without build the query dinamically?

3 Answers 3

1

You should use a Specification for this instead and conditionally add predicates to your where clause with the JPA Criteria API. That way, your query plan will be better than with this generic solution and in addition it also doesn't use something that works by accident. Note that this query SELECT t FROM table t where COALESCE(:codes) IS NULL OR t.code IN (:codes) won't work anymore with Hibernate 6.

Sign up to request clarification or add additional context in comments.

3 Comments

It doesn't work by accident, it works by design. I've never used the specification api, if you can point out how to build this behavior in there I might more useful than just say that it "works by accident"
His point is that you should create the query programmatically based on the parameters you want to pass. You can do it using the Criteria API, or by not concatenating the where clause when codes is empty.
I am one of the Hibernate developers and I can tell you that using a list parameter anywhere other than in an IN predicate is actually illegal and only works by accident. So if you want your code to still work with Hibernate 6, and also want your database to be able to provide you results fast, you should look into the JPA Criteria API approach with Spring Data Specification :)
0

Not the best answer but I found the solution on stackoverflow https://stackoverflow.com/a/54035166/5679560

The solution was simply to use COALESCE in addition to IS NULL so it can work with multiple values.

SELECT t FROM table t where COALESCE(:codes) IS NULL OR t.code IN (:codes)

Comments

-1

your arrays should be made of primitive types for hql to propperly compare each one

in your pseudocode example, instead of

select * from table t where t.code IN (Set<Integer>)

it should be

select * from table t where t.code IN (int[])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.