1

I am currently facing an issue with JPA Query. I have a class Event and a class Race, an event has a list of races. Event and Race have an attribute type Point from lib org.locationtech.jts.geom.Point to handle Geometry object of my PostgreSQL (extended with PostGis) database.

public class Event {

    @OrderBy("rank")
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "event", orphanRemoval = true)
    protected List<Race> races;

    private Point locapoint;

    ...

}

public class Race {

   @ManyToOne(fetch = FetchType.LAZY, optional = false)
   @JsonIgnore
   private Event event;

   private boolean hasAddressEvent;

   private Point locapoint; //null if hasAddressEvent is true

   ...

}

This query works fine in PGSQL (extended with Postgis) :

SELECT distinct e.* FROM Event e inner join Race r on e.id = r.event_id 
where ((:radius is null or :point is null) 
or (r.has_address_event = TRUE and st_distancesphere(:point, e.locapoint) < :radius)
or (r.has_address_event = FALSE and st_distancesphere(:point, r.locapoint) < :radius))

it returns all events that have at least one race located in the circle drawn with these two entries :point (example of value : ST_Point(3.2727,50.2788)) and :radius (integer that represents meters).

Problem is to use it in @Query JPA in my EventRepository :

@Query(value = "SELECT distinct e.* "
            + "FROM Event e inner join Race r on e.id = r.event_id " +
            "where " +
            "((:radius is null or :point is null) " +
            "or (r.has_address_event = TRUE and st_distancesphere(:point, e.locapoint) < :radius) " +
            "or (r.has_address_event = FALSE and st_distancesphere(:point, r.locapoint) < :radius))"
            , nativeQuery = true)
    Page<Event> search(Pageable page, @Param("point") Point point, @Param("radius") Integer radius);

It works only if point and radius params are not null. For example if radius is null, I have this error :

PSQLException: ERROR: operator does not exist : double precision < bytea

It's like if conditions where not short-circuited : even if the first condition returns false it continues to treat the condition.

(:radius is null or :point is null)

With some research, I found this : http://randomthoughtsonjavaprogramming.blogspot.com/2015/10/making-mistakes-in-jpql.html

This lets me think that the problem is my query is turning in SQL and completly changing my condition's structure.

I tried to do equivalent query in JPQL (instead of native PGSQL) and it's the same result.

How can I fix it or just workaround.

Sorry for my english Thanks in advance, Thomas

EDIT :

As suggest @hqrd, I can do the null condition treatment inside my service and use two differents queries :

default Page<Event> search(Pageable page,  Point point,  Integer radius) {
    if (point == null || radius == null) {
        return findAll(page);
    } else {
        return searchAround(page, point, radius);
    }

}

It will be a good solution for the example I introduced in my post. But this query is just a POC, my final query will be more sophisticated (with more conditions, with 6 parameters that can potentially be null).

1
  • Facing the same issue right now, I'm losing it Commented May 20, 2024 at 22:29

1 Answer 1

0

I don't know how to solve this in the @Query, but I suggest you split your issue using java.

@Query(value = "SELECT distinct e.* FROM Event e inner join Race r on e.id = r.event_id " +
        "where (r.has_address_event = TRUE and st_distancesphere(:point, e.locapoint) < :radius) " +
        "or (r.has_address_event = FALSE and st_distancesphere(:point, r.locapoint) < :radius))"
        , nativeQuery = true)
Page<Event> searchAround(Pageable page, @Param("point") Point point, @Param("radius") Integer radius);

default Page<Event> search(Pageable page,  Point point,  Integer radius) {
    if (point == null || radius == null) {
        return findAll(page);
    } else {
        return searchAround(page, point, radius);
    }

}

This way you have more control on your requests.

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

2 Comments

Yes it could be a good solution for the query I introduced. But this query is just a POC, the final one will be more sophisticated (more than 2 values that can be null). Thanks for your answer :)
Maybe try some of the answers here stackoverflow.com/questions/36834537/…

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.