Reputation: 290
I have the following sample query that terminates in < 0.5 second and returns data via Hibernate:
Query qry = em.createQuery(
"select e from Example e where e.ids in :ids ")
.setParameter("ids", ids); // List<String> ids
Since the list can be null or empty, I included the following trivial condition check that terminates just as quickly on the database side:
Query qry = em.createQuery(
"select e from Example e where (:idFilterUsed = false OR e.ids in :ids ) ")
.setParameter("ids", ids) // List<String>
.setParameter("idFilterUsed", idFilterUsed); // boolean
Even if the lower query should seem to have only one small trivial condition more, the query and mapping takes between 12 and 20 seconds instead of < 0.5s !
I can not explain what I have already done and what has not helped me :
Anybody have an idea what it could be or are there alternatives to throw out such IN queries should a condition be present? Many of my queries need several such condition checks.
The queries run on an Oracle 12g Database and im using Hibernate 5.4.27.
edit: To avoid misunderstandings -> the query has this extreme performance loss IF the input list (ids) is filled with at least one ID and idFilterUser = true
. It is logical that the query is slow when the list is empty, but practically this got no influence because there are more conditions attached to it.
Upvotes: 0
Views: 394
Reputation: 2841
The clause :idFilterUsed = false
has nothing to do with the database.
I suggest two appropriate options to skip condition:
1. For one optional parameter
if(idFilterUsed) {
qry = em.createQuery(
"select e from Example e where e.ids in :ids")
.setParameter("ids", ids);
} else {
qry = em.createQuery("select e from Example e");
}
2. For multiple optional parameters use Criteria API
or Spring Specification.
public class ExampleSpecification {
public static Specification<Example> idIn(List<Long> ids, boolean idFilterUsed) {
return (root, query, builder) -> {
if (!idFilterUsed) {
return builder.conjunction();
}
return root.get("ids").in(ids);
};
}
}
public interface ExampleRepository
extends JpaSpecificationExecutor<Example> {
}
List<Long> ids = Arrays.asList(1L, 2L, 5L);
boolean idFilterUsed = false;
exampleRepository.findAll(ExampleSpecification.idIn(ids, idFilterUsed));
Look an example here
Upvotes: 1