After https://github.com/jakartaee/persistence/issues/519 is done, we should consider some convenience methods which we could implement through default methods in terms of existing functions. I would propose the following:
Expression<Character> StringExpression#charAt(Expression<Integer>) as cast(substring(expr, arg1, 1) as Character)
Predicate StringExpression#contains(Expression<String>) as expr like concat('%', arg1, '%')
Predicate StringExpression#containsIgnoreCase(Expression<String>) as lower(expr) like concat('%', lower(arg1), '%')
Predicate StringExpression#startsWith(Expression<String>) as expr like concat(arg1, '%')
Predicate StringExpression#startsWithIgnoreCase(Expression<String>) as lower(expr) like concat(lower(arg1), '%')
Predicate StringExpression#endsWith(Expression<String>) as expr like concat('%', arg1)
Predicate StringExpression#endsWithIgnoreCase(Expression<String>) as lower(expr) like concat('%', lower(arg1))
variants that take literals.
We could also consider the following additions which I think improve readability:
Predicate Expression#equalToAll(Subquery<T>) as this.equalTo(arg1.all())
Predicate Expression#equalToAny(Subquery<T>) as this.equalTo(arg1.any())
Predicate Expression#notEqualToAll(Subquery<T>) as this.notEqualTo(arg1.all())
Predicate Expression#notEqualToAny(Subquery<T>) as this.notEqualTo(arg1.any())
Predicate NumberExpression#gtAll(Subquery<T>) as this.gt(arg1.all())
Predicate NumberExpression#gtAny(Subquery<T>) as this.gt(arg1.any())
Predicate NumberExpression#geAll(Subquery<T>) as this.ge(arg1.all())
Predicate NumberExpression#geAny(Subquery<T>) as this.ge(arg1.any())
Predicate NumberExpression#ltAll(Subquery<T>) as this.lt(arg1.all())
Predicate NumberExpression#ltAny(Subquery<T>) as this.lt(arg1.any())
Predicate NumberExpression#leAll(Subquery<T>) as this.le(arg1.all())
Predicate NumberExpression#leAny(Subquery<T>) as this.le(arg1.any())
Predicate ComparableExpression#greaterThanAll(Subquery<T>) as this.greaterThan(arg1.all())
Predicate ComparableExpression#greaterThanAny(Subquery<T>) as this.greaterThan(arg1.any())
Predicate ComparableExpression#greaterThanOrEqualToAll(Subquery<T>) as this.greaterThanOrEqualTo(arg1.all())
Predicate ComparableExpression#greaterThanOrEqualToAny(Subquery<T>) as this.greaterThanOrEqualTo(arg1.any())
Predicate ComparableExpression#lessThanAll(Subquery<T>) as this.lessThan(arg1.all())
Predicate ComparableExpression#lessThanAny(Subquery<T>) as this.lessThan(arg1.any())
Predicate ComparableExpression#lessThanOrEqualToAll(Subquery<T>) as this.lessThanOrEqualTo(arg1.all())
Predicate ComparableExpression#lessThanOrEqualToAny(Subquery<T>) as this.lessThanOrEqualTo(arg1.any())
I prefer to write and read expr.gtAll(subquery) over expr.gt(subquery.all()) or expr.gt(cb.all(subquery)). Thinking about this a bit more, we could even drop the all(), any() and some() methods in Subquery which I added as part of https://github.com/jakartaee/persistence/issues/519 in favor of the listed methods. AFAIK, there is no other valid use for the subquery quantifiers than with the relational comparison operators.
After https://github.com/jakartaee/persistence/issues/519 is done, we should consider some convenience methods which we could implement through default methods in terms of existing functions. I would propose the following:
Expression<Character> StringExpression#charAt(Expression<Integer>)
ascast(substring(expr, arg1, 1) as Character)
Predicate StringExpression#contains(Expression<String>)
asexpr like concat('%', arg1, '%')
Predicate StringExpression#containsIgnoreCase(Expression<String>)
aslower(expr) like concat('%', lower(arg1), '%')
Predicate StringExpression#startsWith(Expression<String>)
asexpr like concat(arg1, '%')
Predicate StringExpression#startsWithIgnoreCase(Expression<String>)
aslower(expr) like concat(lower(arg1), '%')
Predicate StringExpression#endsWith(Expression<String>)
asexpr like concat('%', arg1)
Predicate StringExpression#endsWithIgnoreCase(Expression<String>)
aslower(expr) like concat('%', lower(arg1))
variants that take literals.
We could also consider the following additions which I think improve readability:
Predicate Expression#equalToAll(Subquery<T>)
asthis.equalTo(arg1.all())
Predicate Expression#equalToAny(Subquery<T>)
asthis.equalTo(arg1.any())
Predicate Expression#notEqualToAll(Subquery<T>)
asthis.notEqualTo(arg1.all())
Predicate Expression#notEqualToAny(Subquery<T>)
asthis.notEqualTo(arg1.any())
Predicate NumberExpression#gtAll(Subquery<T>)
asthis.gt(arg1.all())
Predicate NumberExpression#gtAny(Subquery<T>)
asthis.gt(arg1.any())
Predicate NumberExpression#geAll(Subquery<T>)
asthis.ge(arg1.all())
Predicate NumberExpression#geAny(Subquery<T>)
asthis.ge(arg1.any())
Predicate NumberExpression#ltAll(Subquery<T>)
asthis.lt(arg1.all())
Predicate NumberExpression#ltAny(Subquery<T>)
asthis.lt(arg1.any())
Predicate NumberExpression#leAll(Subquery<T>)
asthis.le(arg1.all())
Predicate NumberExpression#leAny(Subquery<T>)
asthis.le(arg1.any())
Predicate ComparableExpression#greaterThanAll(Subquery<T>)
asthis.greaterThan(arg1.all())
Predicate ComparableExpression#greaterThanAny(Subquery<T>)
asthis.greaterThan(arg1.any())
Predicate ComparableExpression#greaterThanOrEqualToAll(Subquery<T>)
asthis.greaterThanOrEqualTo(arg1.all())
Predicate ComparableExpression#greaterThanOrEqualToAny(Subquery<T>)
asthis.greaterThanOrEqualTo(arg1.any())
Predicate ComparableExpression#lessThanAll(Subquery<T>)
asthis.lessThan(arg1.all())
Predicate ComparableExpression#lessThanAny(Subquery<T>)
asthis.lessThan(arg1.any())
Predicate ComparableExpression#lessThanOrEqualToAll(Subquery<T>)
asthis.lessThanOrEqualTo(arg1.all())
Predicate ComparableExpression#lessThanOrEqualToAny(Subquery<T>)
asthis.lessThanOrEqualTo(arg1.any())
I prefer to write and read
expr.gtAll(subquery)
overexpr.gt(subquery.all())
orexpr.gt(cb.all(subquery))
. Thinking about this a bit more, we could even drop theall()
,any()
andsome()
methods inSubquery
which I added as part of https://github.com/jakartaee/persistence/issues/519 in favor of the listed methods. AFAIK, there is no other valid use for the subquery quantifiers than with the relational comparison operators.Some of the proposals are inspired by https://github.com/querydsl/querydsl/blob/master/querydsl-core/src/main/java/com/querydsl/core/types/dsl/StringExpression.java etc.