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
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();
}
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();
}
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.
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).
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();