Skip to content

Instantly share code, notes, and snippets.

@peterkeller
Created December 7, 2020 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterkeller/d79b5e842caa8da02bdbcf2f7ee51cb7 to your computer and use it in GitHub Desktop.
Save peterkeller/d79b5e842caa8da02bdbcf2f7ee51cb7 to your computer and use it in GitHub Desktop.
JPA CriteriaBuilder with Sub-String Matching
// Take sub-string before first space ' ' if there is any or else take the whole string
private static Expression<String> nameSplit(
Root<Person> root,
CriteriaBuilder builder,
SingularAttribute<Person, String> str
) {
Expression<Integer> indexStart = builder.literal(1);
Expression<Integer> indexOfFirstSpace = builder.locate(root.get(str), " ");
Expression<Integer> stringLength = builder.length(root.get(str));
// if indexOfFirstSpace = 0, then no space ' ' is found
Predicate notFound = builder.equal(indexOfFirstSpace, builder.literal(0));
// indexEnd = index of the first space ' ' or whole string if there isn't any space ' '
Expression<Integer> indexEnd = builder.<Integer>selectCase().when(notFound, stringLength).otherwise(indexOfFirstSpace);
return builder.trim(builder.substring(root.get(str), indexStart, indexEnd));
}
private static Expression<String> firstNameSplit(final Root<Person> root, final CriteriaBuilder builder) {
return nameSplit(root, builder, Person_.firstNameNormalized);
}
public static Specification<Person> getSpecificationByFilter(SimilarPersonFilter filter) {
return (root, query, builder) -> SimilarOrganisationSpecification.buildCompetitionEntryFilterPredicate(filter, root, query, builder);
}
private static Predicate buildCompetitionEntryFilterPredicate(
SimilarPersonFilter filter,
Root<Organisation> root,
CriteriaQuery<?> query,
CriteriaBuilder builder
) {
List<Predicate> orPredicates = new ArrayList<>();
Expression<String> fistNameSplit = firstNameSplit(root, builder);
orPredicates.add(builder.and(
builder.equal(fistNameSplit, filter.getFirstNameNormalizedSplit()),
builder.equal(root.get(Person_.lastNameNormalized), filter.getLastNameNormalized()),
root.get(Person_.dateOfBirth).in(filter.getDateOfBirth())
));
// other predicates
query.distinct(true);
return builder.or(toArray(orPredicates));
}
private static Predicate[] toArray(List<Predicate> predicates) {
return predicates.toArray(new Predicate[0]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment