简体   繁体   中英

Hibernate JPA: 'IS EMPTY' condition doesn't work for collections passed as parameters

I'm trying to write a query in which I need to check whether the collection passed as a parameter empty or not .

I'm writing something like this:

@Query("SELECT u FROM User u" +
        "WHERE" +
        "   :ids IS EMPTY" +
        "   OR u.id IN :ids")
Collection<User> findUsers(@Param("ids") Collection<String> ids);

This code fails on startup with QuerySyntaxException: ??? is not mapped QuerySyntaxException: ??? is not mapped . The stack-trace doesn't give any valuable information, but I found out that if I remove the next part:

:ids IS EMPTY

it starts working.

Q: How to use IS EMPTY for query parameters? Or how to check that collection is empty in any other way?

Note:

  • I'm using Spring Boot 1.5.8.RELEASE.
  • I also looked on "Passing empty list as parameter to JPA query throws error" which is different and didn't help.
  • The code I posted is primitive, it was added just for illustration purpose, my real query is quite complex and I really need to check collection emptiness.

The JPA documentation clearly states, that you should avoid empty collections as parameters.

4.6.8 In Expressions from the JPA 1.0 specification

There must be at least one element in the comma separated list that defines the set of values for the IN expression.

If you think about it, JPA can't do much about it. if the query contains WHERE id in ?0 - how to handle an empty collection? WHERE id in () is invalid syntax, as well as WHERE id in ... So it would neet to remove the whole where-constraint, which is not what is desired in most situations.

Guess you need to handle this in your Application rather than on a query level.

Side-Node: If you are working with filter values with only little options, you could get the result by adding ALL ids, if the user does not select something, ie

where color_id in (1,2,..,10) and type_id in (1,2,3) AND tile_id in (1,2,..,5)
instead of the invalid
where color_id in () and type_id in () AND tile_id in ()

Just not working, if you have thousands of options, or you'll exceed the query length.

In your query, you ask the database to check on the value of :ids , which is not a column in the database, but a Collection in your Java program.

So naturally the persistence framework has no idea what you are talking about and tells you "... is not mapped", which is true.

I think you probably wanted the following query:

@Query("SELECT u FROM User u" +
    "WHERE" +
    "   u.id IS NULL" +
    "   OR u.id IN :ids")

If that is not the case, please describe what you want to achieve with the query.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM