Dynamic JPA OR Expression - jpa

How can I construct Criteria Query to update status of multiple items?
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaUpdate<Item> query = builder.createCriteriaUpdate(Item.class);
Root<Item> root = query.from(Item.class);
List<Predicate> predicates = new ArrayList<Predicate>();
for(Long id : itemIds)
{
predicates.add(builder.or(builder.equal(root.get(Item_.id), id)));
}
query.set(root.get(Item_.status), status)
.where(predicates.toArray(new Predicate[predicates.size()]));
entityManager.createQuery(query).executeUpdate();
The above query only work if itemIds. size() == 1. If the itemIds.size() > 2 then the entities will not be updated. Can anyone help to construct correct predicate for OR expression please.
Thank in advance!

Related

Creating Criteria By And or Or on Runtime by JPA Repository

I need to create a query by deciding on runtime. Basically I have few parameters and one of them will specify If I should use And or Or to combine criterias. By using Spring JPA Repository how can I do it? It is easy to do it for parameters as :
#Query(value = "SELECT u FROM User u WHERE u.name IN :names")
List<User> findUserByNameList(#Param("names") Collection<String> names);
But if I want to add one more criteria lets say size, and I need to decide which one of (AND,OR) to use to combine criteria, how can I do it?
Example:
SELECT u FROM User u WHERE u.name IN :names OR/AND size = 10;
public List<User> getUsers(List<String> names, Integer size, boolean useOrPredicate) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
Root<User> user = criteriaQuery.from(User.class);
Predicate predicate1 = user.get("name").in(names);
Predicate predicate2 = criteriaBuilder.equal(user.get("size"), size);
Predicate predicate;
if(useOrPredicate)
predicate = criteriaBuilder.or(predicate1, predicate2);
else
predicate = criteriaBuilder.and(predicate1, predicate2);
criteriaQuery.where(predicate);
return entityManager.createQuery(criteriaQuery).getResultList();
}

JPA Criteria builder for logical operator OR

I need to prepare a query some thing like below dynamically, I am getting group column in a different list and main column in a different list,
Can some one help me?
SELECT * FROM TABLE WHERE COLUMN_A =1 ? OR (COLUMN_B='A' AND COLUMN_B='Z')
Java code:
CriteriaBuilder builder;
List<Predicate> predicates = new ArrayList<Predicate>();
List<Predicate> innerPredicates = new ArrayList<Predicate>();
List<Predicate> outerPredicates = new ArrayList<Predicate>();
for(GroupClause gc : list.getGroupClause()){
List<Predicate> groupPredicates = new ArrayList<Predicate>();
groupPredicates.add(gc.getColumnB());
if(groupPredicates!=null && groupPredicates.size()>0){
innerPredicates.add(builder.and(groupPredicates.toArray(new Predicate[groupPredicates.size()])));
}
}
if(outerPredicates.size()>0){
predicates.add(builder.or(outerPredicates.toArray(new Predicate[outerPredicates.size()])));
predicates.add(builder.or(innerPredicates.toArray(new Predicate[innerPredicates.size()])));
}
The put for above code is
SELECT * FROM TABLE WHERE COLUMN_A =1 ? AND COLUMN_B='A' AND COLUMN_B='Z'
Use simple Criteria here is the example
public List<TABLE> getTABLE () {
Criteria tableCriteria= session.createCriteria(TABLE.class);
tableCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
tableCriteria.add(Restrictions.and(Restrictions.eq("COLUMN_A",1),Restrictions.or(Restrictions.eq("COLUMN_B","A"),
Restrictions.eq("COLUMN_B","Z")))
return tableCriteria.list();
}

JPA CriteriaBuilder - not in a Collection

What is the difference between:
First test run on the Builder:
Predicate predicate = root.get(PersonEntity_.name).in(names);
criteriaBuilder.not(predicate);
Second test run on the Query:
Predicate predicate2 = root.get(PersonEntity_.name).in(names).not();
criteriaQuery.where(predicate2);
This seems to give the same results. Am I missing something? Should we choose the CriteriaBuilder above the CriteriaQuery?
Complete example:
List<String> names = new ArrayList<String>();
names.add("John");
names.add("Emma");
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonEntity> criteriaQuery = criteriaBuilder.createQuery(PersonEntity.class);
Root<PersonEntity> root = criteriaQuery.from(PersonEntity.class);
// First test run on the Builder
Predicate predicate = root.get(PersonEntity_.name).in(names);
criteriaBuilder.not(predicate);
// Second test run the query
// Predicate predicate2 = root.get(PersonEntity_.name).in(names).not();
// criteriaQuery.where(predicate2);
List<PersonEntity> list = entityManager.createQuery(cq).getResultList();
There is not difference between these variants. Both statements result in the same.

Difference between CriteriaBuilder and CriteriaQuery for a Collection

What is the difference between:
criteriaBuilder.in(predicate);
criteriaQuery.where(predicate);
This seems to give the same results. Am I missing something? Should we choose the builder above the query?
Complete example:
List<String> names = new ArrayList<String>();
names.add("John");
names.add("Emma");
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonEntity> criteriaQuery = criteriaBuilder.createQuery(PersonEntity.class);
Root<PersonEntity> root = criteriaQuery.from(PersonEntity.class);
Predicate predicate = root.get(PersonEntity_.name).in(names);
criteriaBuilder.in(predicate);
// or alternative: criteriaQuery.where(predicate);
List<PersonEntity> list = entityManager.createQuery(cq).getResultList();
criteriaBuilder.in(predicate) creates a new predicate. You should file a bug with your provider if it is adding the predicate to the query, as this will not be portable. According to the specification it creates a new predicate, just as root.get(PersonEntity_.name).in(names) does. The query should only use the predicate if it gets added to it such as by calling criteriaQuery.where(predicate).

JPA CriteriaQuery: getCount + condition

I try to get all the count of Articles (Article.class) which are not analyzed (analyzed == false).
Sadly the following code returns absolutely wrong numbers.
Would anybody know why?
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> query = cb.createQuery(Long.class);
query.select(cb.count(query.from(Article.class)));
Root<Article> articles = query.from(Article.class);
Predicate condition = cb.isFalse(articles.get(Article_.analyzed));
query.where(condition);
TypedQuery<Long> unanalyzedArticlesAmount = entityManager.createQuery(query);
return unanalyzedArticlesAmount.getSingleResult();
finally read this post:
How to count the number of rows of a JPA 2 CriteriaQuery in a generic JPA DAO?
and found the following solution:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery();
Root<Article> root = query.from(Article.class);
query.select(cb.count(root));
Predicate condition = cb.isFalse(root.get(Article_.analyzed));
query.where(condition);
TypedQuery<Long> unanalyzedArticlesAmount = entityManager.createQuery(query);
return unanalyzedArticlesAmount.getSingleResult();