I want to create a Java Criteria Api Predicate that performs the equivalent SQL query in Postgres 15 as follows:
SELECT time_range_column FROM public.address_table
WHERE time_range_column && '[2014-09-23, 2015-09-24]'::tsrange;
I declared the time_range_column in my entity as follows:
@Type(PostgreSQLRangeType.class)
@Column(name = "time_range_column")
private Range\<LocalDateTime\> timeRangeColumn;
My solution is as follows, but returns no results:
String dateTimeString1 = "2014-09-15 00:00:00";
String dateTimeString2 = "2015-09-15 00:00:00";
String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateTimeFormat);
LocalDateTime d1 = LocalDateTime.parse(dateTimeString1, formatter);
LocalDateTime d2 = LocalDateTime.parse(dateTimeString2, formatter);
String rangeLiteral = "[" + d1 + "," + d2 + ")";
Predicate dateRangePredicate = criteriaBuilder.and(criteriaBuilder.literal(rangeLiteral)
.in(root.<LocalDateTime>get("time_range_column")));
How to create the predicate that overlaps these dates?
TL;DR
::or&&are not part of theJPA Criteria APIstandard. You could use a native SQL query.If you want to use specific features or functions unique to a database system like
PostgreSQL, it may not be possible to use them directly within the JPA Criteria API.Some queries, you can avoid the headache by specifying the escape sequence completely, but for this query; There is no way to simultaneously escape special types such as
overlap (&&),double colon (::), andtsrange (cast(string as tsrange)).It would be appropriate to create this query using a native query (@Query) instead of the Criteria API, or alternatively; if you are using
Hibernateyou can create aFunctionContributorfor this statement.Create a FunctionContributor, here we give our function a special name and set our pattern:
(It is a simple function definition approach, it can be made more usable.)
We use this function with the Criteria API:
The class must be then registered via Java ServiceLoader mechanism by adding full name of the class with its packages into the file with name
org.hibernate.boot.model.FunctionContributorinto the java module’sMETA-INF/servicesdirectory.You use this specification your query will look like this:
It was prepared with
Spring Boot 3.2.1andHibernate 6.2.7.Final.