JPAstreamer Predicates

In JPAstreamer, the concept of fields and predicates is of central importance to achieve optimal performance. If you haven’t already, we recommend reading the chapter How JPAstreamer Works, to understand how fields are used by the JPAstreamer renderer to obtain optimized JPA queries.

What is a Predicate?

Predicate<T> is a functional Java interface. An instance implementing this interface has a boolean function test that takes a parameter of type T and returns either true or false. JPAstreamer uses such predicates as arguments for Stream operations i.e. filter() and sort().

Here is an example that uses a Predicate<String> to return true if the String begins with an "A" and false otherwise:

Predicate<String> startsWithA = (String s) -> s.startsWith("A");

Stream.of("Snail", "Ape", "Bird", "Ant", "Alligator")
    .filter(startsWithA)
    .forEachOrdered(System.out::println);

This will print all animals that starts with "A": Ape, Ant and Alligator because the filter operator will only pass forward those elements where its Predicate returns true.

The official JavaDoc contains more information about the interface Predicate<T>.

Fields

The fields included as part of the JPAstreamer metamodel (described here) can be used to produce Predicates that are related to the field.

Here is an example of how a StringField can be used in conjuction with a Film object:

jpaStreamer.stream(Film.class)
    .filter(Film$.title.startsWith("A"))
    .forEachOrdered(System.out::println);

In this example, the StringField 's method Film$.title::startsWith creates and returns a Predicate<Film> that, when tested with a Film, will return true if and only if that Film has a title that starts with an "A" (otherwise it will return false).

When run, the code above will produce the following output:

Film { filmId = 1, title = ACADEMY DINOSAUR, description = ...
Film { filmId = 2, title = ACE GOLDFINGER, description = ...
...

It would be possible to express the same semantics using a standard anonymous lambda:

films.stream()
    .filter(f -> f.getTitle().startsWith("A"))
    .forEachOrdered(System.out::println);

but JPAstreamer would not be able to recognize and optimize such vanilla lambdas. This means JPAstreamer is forced to pull in the entire Film table and then apply the predicates in the JVM. Because of this, developers are highly encouraged to use the provided Fields when obtaining predicates because these predicates will always be recognizable by the JPAstreamer query optimizer.

Do this: filter(Film$.title.greaterOrEqual("He"))
Don’t do this: filter(f → "He".compareTo(f.getTitle()) ⇐ 0)

Field types

JPAstreamer uses a variety of field types to represent the attributes of the entity-classes. This is partly due to the fact that different types are compatible with different operations, but also for performance reasons.

Below is a table describing how attribute types are mapped to fields.

Table 1. How JPAstreamer’s metamodel represents the attribute types as fields
Attribute type Field type

int

IntField<ENTITY>

double

DoubleField<ENTITY>

float

FloatField<ENTITY>

byte

ByteField<ENTITY>

long

LongField<ENTITY>

short

ShortField<ENTITY>

char

CharField<ENTITY>

Enum

EnumField<ENTITY, Enum>

bool

BooleanField<ENTITY>

String

StringField<ENTITY>

Integer

ComparableField<ENTITY, Integer>

Double

ComparableField<ENTITY, Double>

Float

ComparableField<ENTITY, Float>

Byte

ComparableField<ENTITY, Byte>

Long

ComparableField<ENTITY, Long>

Short

ComparableField<ENTITY, Short>

Character

ComparableField<ENTITY, Character>

Boolean

ComparableField<ENTITY, Boolean>

CustomType

ReferenceField<ENTITY, CustomType>

Class<T>[]

ReferenceField<ENTITY, Class<?>[]>

Set<T>

ReferenceField<ENTITY, Set<?>>

Map<T>

ReferenceField<ENTITY, Map<?>>

List<T>

ReferenceField<ENTITY, List<?>>

LocalDate

ComparableField<ENTITY, LocalDate>

LocalDateTime

ComparableField<ENTITY, LocalDateTime>

LocalTime

ComparableField<ENTITY, LocalTime>

Calendar

ComparableField<ENTITY, Calendar>

java.util.Date

ComparableField<ENTITY, java.util.Date>

java.sql.Time

ComparableField<ENTITY, java.sql.Time>

java.sql.Date

ComparableField<ENTITY, java.sql.Date>

java.sql.Timestamp

ComparableField<ENTITY, java.sql.Timestamp>

The following chapters will describe how to get predicates from different Field types and how these predicates can be combined and negated.

  1. Reference Predicates describes what predicates can be obtained from ReferenceField

  2. Comparable Predicates describes what predicates can be obtained from ComparableField

  3. Primitive Predicates describes what predicates can be obtained from all primitive fields i.e. IntField and DoubleField

  4. String Fields describes what predicates can be obtained from StringField