I have written a query in Criteria Builder, its looks like this.
private EntityManager entitymanager;
CriteriaBuilder criteriaBuilder = entitymanager.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery =
criteriaBuilder.createQuery(Object.class);
Root<Employee> from = criteriaQuery.from(Employee.class);
criteriaQuery.orderBy(criteriaBuilder.asc(name));
TypedQuery<Object> typedQuery1 = entitymanager.createQuery(criteriaQuery );
List<Object> resultlist1 = typedQuery1.getResultList();
typedQuery1.setMaxResults(pageable.getPageSize());
After setMaxResults apply to the query, the order of the resultlist1 is
different as before?
Why is this happened?
How can I stop this behavior?
Why are you using Object for type? Use Employee
CriteriaQuery<Employee> criteriaQuery =
criteriaBuilder.createQuery(Employee.class);
Root<Employee> from = criteriaQuery.from(Employee.class);
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("column_name")));
TypedQuery<Employee> typedQuery1 = entitymanager.createQuery(criteriaQuery);
typedQuery1.setMaxResults(pageable.getPageSize());
List<Employee> resultlist1 = typedQuery1.getResultList();
Calling setMaxResults() after executing query does not make sense. Set max result before calling getResultList()
typedQuery1.setMaxResults(pageable.getPageSize());
List<Employee> resultlist1 = typedQuery1.getResultList();
What is name variable? Do order by like this:
criteriaQuery.orderBy(criteriaBuilder.asc(from.get("column_name")));
Related
I have the below piece of the code to get count query form the original query.
But this is the line causing the issue at compile time.
countQuery.from(sqmSubQuery);
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
SqmSubQuery sqmSubQuery = (SqmSubQuery<Tuple>) countQuery.subquery(Tuple.class);
SqmSelectStatement sqmOriginalQuery = (SqmSelectStatement) query;
SqmQuerySpec sqmOriginalQuerySpec = sqmOriginalQuery.getQuerySpec();
sqmSubQuery.setQueryPart(sqmOriginalQuerySpec.copy(SqmCopyContext.simpleContext()));
Root<T> subQuerySelectRoot = (Root<T>) sqmSubQuery.getRoots().iterator().next();
sqmSubQuery.multiselect(subQuerySelectRoot.get("id").alias("id"));
countQuery.select(builder.count(builder.literal(1)));
countQuery.from(sqmSubQuery);
Based on you comment you want to select the distinct count of all employee types. The query you provided should be equivalent to SELECT COUNT(DISTINCT employee_type) FROM Employee.
This can be written in JPA as shown below:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
Root<Employee> employeeRoot = countQuery.from(Employee.class);
countQuery.select(builder.countDistinct(employeeRoot.get("type")));
Long count = entityManager.createQuery(countQuery).getSingleResult();
where type is the name of the property that maps to the column employee_type
The type org.hibernate.query.criteria.JpaSelectCriteria declares this method:
<X> JpaDerivedRoot<X> from(jakarta.persistence.criteria.Subquery<X> subquery);
which is the one you need to call if you're trying to use a subquery in the from clause.
And SqmSelectStatement implements JpaSelectCriteria. (It is also the object which implements jakarta.persistence.criteria.CriteriaQuery.)
So you can cast any CriteriaQuery to JpaSelectCriteria and call from():
CriteriaQuery<Thing> query = ... ;
Subquery<OtherThing> subquery = ... ;
((JpaSelectCriteria<Thing>) query).from(subquery);
or whatever (I did not test this code).
please help me out writing criteria builder for this query
SELECT *
FROM XYZ
WHERE date_v < "2020/01" AND
id NOT IN (SELECT id FROM XYZ WHERE date_v = '2020/01')
i have looked at using subqueries in jpa criteria api but i am unable to figure it
I have tried using subquery and joins but it throwing different error after all i get to know that i need to get more clarity about query criteria usages. any help much appreciated
You have to create XyzEntity with Long id and LocalDate date_v fields.
// query
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<XyzEntity> query = cb.createQuery(XyzEntity.class);
Root<XyzEntity> root = query.from(XyzEntity.class);
LocalDate date = LocalDate.of(2020, 1, 1);
// subquery
Subquery<Long> subQuery = query.subquery(Long.class);
Root<XyzEntity> subRoot = subQuery.from(XyzEntity.class);
Predicate idSubPredicate = cb.equal(root.get("id"), subRoot.get("id"));
Predicate dateSubPredicate = cb.equal(subRoot.get("date_v"), date);
subQuery.select(subRoot.get("id")).where(idSubPredicate, dateSubPredicate);
// query predicates
Predicate datePredicate = cb.greaterThan(root.get("date_v"), date);
Predicate notExistsPredicate = cb.exists(subQuery).not();
// query result
query.select(root).where(datePredicate, notExistsPredicate);
List<XyzEntity> result = entityManager.createQuery(query).getResultList();
I have mentioned the corrections in comments for the answer but I feel providing full solution seems good and helps others:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Entity> query = cb.createQuery(Entity.class);
Root<Entity> root = query.from(Entity.class);
// subquery
Subquery<Long> subQuery = query.subquery(Long.class);
Root<Entity> subRoot = subQuery.from(Entity.class);
Predicate subPredicate = cb.equal(subRoot.get("date_v"), dateValue);
subQuery.select(subRoot.get("id")).where(subPredicate);
// query predicates
Predicate datePredicate = cb.lessThan(root.get("date_v"), dateValue);
Predicate notExistsPredicate = root.get("id").in(subQuery).not();
// query result
query.select(root).where(datePredicate, notExistsPredicate);
Query d = entityManager.createQuery(query);
List<Entity> resultList = d.getResultList()
I'm trying to delete a bunch of objects with one query using the CriteriaBuilder API. I'm looking for something like this select:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> query = criteriaBuilder.createQuery(entityClass);
Root<T> root = query.from(entityClass);
query.select(root).where(/*some condition*/);
return entityManager.createQuery(query).getResultList();
but then a delete instead of a select. As far as I can see, there's no remove or delete method on CriteriaQuery. Is it possible using this API?
I can of course execute the select, then call entityManager.remove(object) for each result, but that feels very inefficient.
Try this:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaDelete<SomeClass> query = criteriaBuilder.createCriteriaDelete(SomeClass.class);
Root<SomeClass> root = query.from(SomeClass.class);
query.where(root.get("id").in(listWithIds));
int result = entityManager.createQuery(query).executeUpdate();
The where clause can laso look like this:
query.where(criteriaBuilder.lessThanOrEqualTo(root.get("id"), someId));
in JPA 2.1, there are Criteria APIs exactly as what you want.it looks like this:
CriteriaBuilder cBuilder = em.getCriteriaBuilder();
CriteriaDelete<T> cq = cBuilder.createCriteriaDelete(entityClass);
Root<T> root = cq.from(entityClass);
cq.where(/*some codition*/);
int result = em.createQuery(cq).executeUpdate();
you can refert to JPA 2.1 SPEC and API here
i chanced upon this Criteria example
http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/Criteria
EntityManager em = getEntityManager();
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Employee> query = qb.createQuery(Employee.class);
Root<Employee> employee = query.from(Employee.class);
query.where(qb.equal(employee.get("firstName"), "Bob"));
List<Employee> result = em.createQuery(query).getResultList();
...
My question is, is there anyway i can specify the field name (firstName) in a compile time manner?
Have you tried passing the fieldname as a variable?
String filterField = "firstName";
query.where(qb.equal(employee.get(filterField), "Bob"));
Using it in a dynamic way should be the main point of that api.
My named query looks like this, thanks to here.
#NamedQuery(
name="Cat.favourites",
query="select c
from Usercat as uc
inner join uc.cat as c
where uc.isFavourtie = true
and uc.user = :user")
And the call to implement looks like this :
Session session = sessionFactory.getCurrentSession();
Query query = session.getNamedQuery("Cat.favourites");
query.setEntity("user", myCurrentUser);
return query.list();
What would be the equivalent criteria query that returns a list of cats ?
With JPA 2.0 Criteria:
(This is one of the many ways you can achieve this using JPA 2.0 Criteria api)
final CriteriaQuery<Cat> cq = getCriteriaBuilder().createQuery(Cat.class);
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final Root<Usercat> uc= cq.from(Usercat.class);
cq.select(uc.get("cat");
Predicate p = cb.equal(uc.get("favourtie", true);
p = cb.and(p, cb.equal(uc.get("user"), user));
cq.where(p);
final TypedQuery<Cat> typedQuery = entityManager.createQuery(cq);
return typedQuery.getResultList();