Difference between CriteriaBuilder and CriteriaQuery for a Collection - jpa

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).

Related

Dynamic JPA OR Expression

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!

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.

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

Simple JPA 2 criteria query "where" condition

I'm learning jpa-hibernate basics.
I have this query for getting all users:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
cq.select(cq.from(Utente.class));
return getEntityManager().createQuery(cq).getResultList();
Now I want to filter by a boolean field named 'ghost' where it equals true (or false, it depends).
Translated:
SELECT * FROM users WHERE ghost = 0;
Do I have to use cq.where() ? How?
Yes, you have to use cq.where().
Try something like this:
Root<Utente> utente = cq.from(Utente.class);
boolean myCondition = true; // or false
Predicate predicate = cb.equal(utente.get(Utente_.ghost), myCondition);
cq.where(predicate);
Where I have used the canonical metamodel class Utente_ that should be generated automatically. This avoids the risk of making errors in typing field names, and enhances type safety. Otherwise you can use
Predicate predicate = cb.equal(utente.get("ghost"), myCondition);

hibernate jpa criteriabuilder ignore case queries

How to do a like ignore case query using criteria builder. For description property I want to do something like upper(description) like '%xyz%'
I have the following query
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> personCriteriaQuery = criteriaBuilder.createQuery(Person.class);
Root<Person> personRoot = personCriteriaQuery.from(Person.class);
personCriteriaQuery.select(personRoot);
personCriteriaQuery.where(criteriaBuilder.like(personRoot.get(Person_.description), "%"+filter.getDescription().toUpperCase()+"%"));
List<Person> pageResults = entityManager.createQuery(personCriteriaQuery).getResultList();
There is a CriteriaBuilder.upper() method:
personCriteriaQuery.where(criteriaBuilder.like(
criteriaBuilder.upper(personRoot.get(Person_.description)),
"%"+filter.getDescription().toUpperCase()+"%"));
If the database contains German words with letters like Fußballschuhe in the column, java will modify the parameter in uppercase method to FUSSBALLSCHUHE and the query will not match. Lowercase will work in this case:
personCriteriaQuery.where(criteriaBuilder.like(
criteriaBuilder.lower(personRoot.get(Person_.description)),
"%"+filter.getDescription().toLowerCase()+"%"));