JPA Criteria API IN expression Parameter list - java

Is there a possibility to use a parameter list in Criteria API .in expression?
I have something like this:
List<Long> list = new ArrayList<Long>();
list.add((long)1);
list.add((long)2);
list.add((long)3);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Bewerbung> criteriaQuery = cb.createQuery(Bewerbung.class);
Root<Bewerbung> bewerbung = criteriaQuery.from(Bewerbung.class);
criteriaQuery.select(bewerbung).where(
cb.in(bewerbung.get(Bewerbung_.bewerberNummer)).value(list);
return em.createQuery(criteriaQuery).getResultList();
The expression .value(list) does not work as value() is expecting a paramter of type long not a list.
In my case it is not possible to use a subquery.
Can anyone help me on this issue?

No need to use CriteriaBuilder#isTrue. This should suffice:
criteriaQuery.select(bewerbung)
.where(bewerbung.get(Bewerbung_.bewerberNummer)
.in(list));

cb.isTrue(bewerbung.get(Bewerbung_.bewerberNummer).in(list));
should do the trick, AFAIK.

Related

Criteria - Order by order different parameters from different conditions

I have a method in Query criteria which returns the "Covers" ordered by their generation date, but also includes those that have "re-entry" between those dates, the method returns the correct covers, but I need it to order them in a special way: If they have a "re-entry" tuple, it uses the re-entry date as order criteria, and if it does not have one, it uses the generation date as criteria. I need to join both criteria in a single order.
The method is the following:
public List<Cover> ListCover(Long startDate, Long finalDate) {
CriteriaBuilder criteria = em.getCriteriaBuilder();
CriteriaQuery<Cover> query = criteria.createQuery(Cover.class);
Root<Cover> cover = query.from(Cover.class);
Subquery<Long> miniQuery = query.subquery(Long.class);
Root<ReEntryCover> reEntryCover = miniQuery.from(ReEntryCover.class);
Predicate predicateMini1 = criteria.between(reEntryCover.get("reEntryDate"), startDate, finalDate);
Predicate predicateMini2 = criteria.equal(reEntryCover.get("coverNumberFK"), cover.get("coverNumber"));
Predicate predicateMiniFinal = criteria.and(predicateMini1, predicateMini2);
miniQuery.select(criteria.max(reEntryCover.get("reEntryDate"))).where(predicateMiniFinal);
Predicate predicate1 = criteria.between(cover.get("coverGenerationDate"), startDate, finalDate);
Predicate predicate2 = criteria.isNotNull(miniQuery);
Predicate predicateFinal = criteria.or(predicate1, predicate2);
query.select(cover).distinct(true).where(predicateFinal).orderBy(criteria.asc(cover.get("coverGenerationDate")));
return em.createQuery(query).getResultList();
}
In other words, I need to put a conditional inside the "order by" so that it doesn't order by generation date in case the cover has a tuple in the "re-entry" table, and instead use the "re-entry date" parameter like sort parameter (use "orderBy(criteria.asc(cover.get("coverGenerationDate"), criteria.asc(cover.get("reEntryDate"))" is not what I need since I want to use the reentry date (if any) as the generation date for ordering).
How is it possible to do this?
I tried to use:
1-
orderBy(criteria.asc(cover.get("coverGenerationDate"), criteria.asc(cover.get("reEntryDate"))
not working.
2-
multiSelect with differents predicates for 2 types of covers, I donĀ“t know how it works.
3-
2 querys is working, but is very slow, i need to do all in 1 query.

Hibernate Restriction to search with like clause in list

I need help with hibernate criteria restriction.
As we know that we use IN restriction with list , i.e
Criteria criteria = session.createCriteria(Student.class);
List<String> studentNames= new ArrayList();
criteria.add(Restrictions.in("name",studentNames);
List list = criteria.list();
and to use like
we use restriction like this i.e
String matchString = "Suraj Kumar";
criteria.add(Restrictions.like(
"studentName", matchString));
Problem: What i want is that every element in list should be searched with "LIKE" clause. If we use IN clause, then it compares the element with all the elements passed in the IN clause, and that comparison is based on equality.
But requirement is that , every element in the list should be checked with the LIKE clause , with the corresponding database column.
Please help me to create hibernate criteria restriction with the same.
Thanks
You can try to use Disjunction which can be used if you have multiple OR conditions.
Criteria criteria = session.createCriteria(Student.class);
List<String> studentNames= new ArrayList();
Disjunction disj = Restrictions.disjunction();
for (String value : studentNames) {
disj.add(Restrictions.like("name", value));
}
criteria.add(disj);
List list = criteria.list();

How to pass multiple value in like clause of Criteria api?

Here is what i am implementing.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> userRoot = query.from(User.class);
List<Predicate> predicates = new ArrayList<>();
Expression<String> userExpression = statusRoot.get("firstName");
for (String str : firstNames) {
predicates.add(cb.like(userExpression, "%" + str + "%"));
}
I want to apply like clause on list of values but its appending all Predicate with AND operator. please help.
Actually code given in example does not show use of predicates. That is where the problem is. I will assume it is equivalent to rather typical:
//conjunction, will combine with 'AND'
query.where(predicates.toArray(new Predicate[0]));
As documented, it will combine Predicates with AND:
Modify the query to restrict the query result according to the
conjunction of the specified restriction predicates
One way to combine Predicates with OR is simply using CriteriaBuilder.or:
//disjunction, will combine with 'OR'
Predicate firstNameLikeAnyOf = cb.or(predicates.toArray(new Predicate[0]));
query.where(firstNameLikeAnyOf);

get all the values in where clause for empty stirng using hibernate

i am building a shopping cart using jsp and hibernate.
i am filtering the content by brand size and price using checkboxes
the checked checkboxes are returned to the class where hql query exists.
so i want i single hql query that can handle this.
as like if one of the parameter like size is empty (means user doesnt uses it to filter the content ) than an empty string is passed to the hql query which returns any value...
so is there anything possible that all values can be retrived in where clause for empty string or some other alternative except coding different methods for different parameter...
I typically use the Criteria api for things like this... if the user does not specify a size, do not add it to the criteria query.
Criteria criteria = session.createCriteria(MyClass.class);
if(size != null && !size.isEmpty()){
criteria.add(Restrictions.eq("size", size);
}
To have multiple restrictions via an OR statement, you use Disjunction. For an AND, you use Conjunction.
Criteria criteria = session.createCriteria(MyClass.class);
Disjunction sizeDisjunction = Restrictions.disjunction();
String[] sizes = { "small", "medium", "large" };
for(int i = 0; i < sizes.length; i++){
sizeDisjunction.add(Restrictions.eq("size", sizes[i]);
}
criteria.add(sizeDisjunction );
First, good practices say that instead of passing and empty String to the query, you should pass null instead. That said, this hql should help you:
from Product p
where p.brand = coalesce(:brand, p.brand)
and p.size = coalesce(:size, p.size)
and p.price = coalesce (:price, p.price)

JPA Criteria Query API and order by two columns

I'm stuck with a simple problem; struggling how to invoke order by on a joined entity. Essentially I am trying to achieve the following with JPA Criteria:
select distinct d from Department d
left join fetch d.children c
left join fetch c.appointments a
where d.parent is null
order by d.name, c.name
I have the following:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Department> c = cb.createQuery(Department.class);
Root<Department> root = c.from(Department.class);
Fetch<Department, Department> childrenFetch = root.fetch(
Department_.children, JoinType.LEFT);
childrenFetch.fetch(Department_.appointments, JoinType.LEFT);
c.orderBy(cb.asc(root.get(Department_.name)));
c.distinct(true);
c.select(root);
c.where(cb.isNull(root.get(Department_.parent)));
How to achieve order by d.name, c.name with Criteria API? I tried with Expression, Path but didn't work.
Any pointers will be greatly appreciated.
If you need to add couple of orders you can make something like (but for your query and different root objects)
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Route> query = criteriaBuilder.createQuery(Route.class);
Root<Route> routeRoot = query.from(Route.class);
query.select(routeRoot);
List<Order> orderList = new ArrayList();
query.where(routeRoot.get("owner").in(user));
orderList.add(criteriaBuilder.desc(routeRoot.get("date")));
orderList.add(criteriaBuilder.desc(routeRoot.get("rating")));
query.orderBy(orderList);
I have the same problem with order by using Criteria API. I found this solution:
CriteriaQuery<Test> q = cb.createQuery(Test.class);
Root<Test> c = q.from(Test.class);
q.select(c);
q.orderBy(cb.asc(c.get("name")), cb.desc(c.get("prenom")));
I was having trouble doing the same, and I have found a solution on this page:
http://www.objectdb.com/api/java/jpa/criteria/CriteriaQuery/orderBy_Order_
//javax.persistence.criteria.CriteriaQuery
//CriteriaQuery<T> orderBy(Order... o)
Specify the ordering expressions that are used to order the query results. Replaces the previous ordering expressions, if any. If no ordering expressions are specified, the previous ordering, if any, is simply removed, and results will be returned in no particular order. The left-to-right sequence of the ordering expressions determines the precedence, whereby the leftmost has highest precedence.
Parameters:
o - zero or more ordering expressions
Returns:
the modified query
Since:
JPA 2.0
The solucion that work for me is the following
session=HibernateUtil.getSessionJavaConfigFactory_report().openSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Object[]> criteriaQuery = builder.createQuery(Object[].class);
List<Order> orderList = new ArrayList();
orderList.add(builder.desc(ejeRoot.get("name")));
criteriaQuery.orderBy(orderList);
Note: ejeRoot is the class object
categoryRepository.findAll(predicates, new Sort(Direction.ASC, "sortOrder", "name"))
.forEach(categoryDtoList::add);

Categories