JPQL query: selecting a single Boolean which is the AND of two of object's fields
Suppose that I have a JPA-annotated class called MyData
with a primary identifier field (BigDecimal
type called "primaryID"), and two Boolean
fields called "fieldA" and "fieldB". 开发者_JAVA百科What I want to do is create a JPA query that will select fieldA AND fieldB
for a given MyData
instance.
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Boolean> boolQuery = builder.createQuery(Boolean.class);
final Root<MyData> data = boolQuery.from(MyData.class);
boolQuery.select(builder.isTrue(builder.and(data.<Boolean> get("fieldA"),
profile.<Boolean> get("fieldB"))));
final Predicate primaryIDPredicate = builder.equal(profile.<BigDecimal> get("primaryID"),
1000);
boolQuery.where(primaryIDPredicate);
final TypedQuery<Boolean> myQuery = entityManager.createQuery(boolQuery);
When my entityManager
executes this query, I get: org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: and near line 1...
. This leads me to believe that I need something different (other than the builder.isTrue
method) to designate that I want to take a Boolean and of two fields of my object. Any ideas on how I should construct this query?
OK, what I ended up doing was simply moving the booleans I wanted to "AND" into the predicate instead, and just checking whether anything was returned. Of course, I could have simply retrieved the entire object (MyData) based on the primary ID, and done the "AND" in Java code, but the point was to avoid fetching the full object because it has a large number of nested joins to its referenced collections, and those would be unnecessary for this case.
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<BigInteger> primaryIDQuery = builder.createQuery(BigInteger.class);
final Root<MyData> data = primaryIDQuery.from(MyData.class);
primaryIDQuery.select(data.<BigInteger> get("primaryId"));
final Predicate primaryIDPredicate = builder.equal(profile.<BigInteger> get("primaryId"),1000);
final Predicate otherPredicate = builder.or(
builder.isTrue(profile.<Boolean> get("fieldA")),
builder.isTrue(profile.<Boolean> get("fieldB")));
primaryIDQuery.where(primaryIDPredicate , otherPredicate);
final TypedQuery<BigInteger> existenceQuery = entityManager.createQuery(primaryIDQuery);
boolean whatIWant = existenceQuery.getResultList().size() > 0;
精彩评论