Implement Hibernate with OrderBy - java

I want to implement Hibernate query with OrderBy clause. I tried this:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<OrdersModel> query = builder.createQuery(OrdersModel.class);
Root<OrdersModel> root = query.from(OrdersModel.class);
query.select(root).orderBy(root.get("added"));
Query<OrdersModel> q = session.createQuery(query);
cdList = q.getResultList();
But I have to cast the .orderBy like this query.select(root).orderBy((List<javax.persistence.criteria.Order>) root.get("added"));
Do you know what is the proper way to implement this?
I tried also this:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<OrdersModel> query = builder.createQuery(OrdersModel.class);
Root<OrdersModel> root = query.from(OrdersModel.class);
query.select(root);
query.orderBy(builder.desc(root.get("added")));
Query<OrdersModel> q = session.createQuery(query).setMaxResults(5);
cdList = q.getResultList();
But the rows order are not displayed properly. The list is not properly sorted.

Related

Problem with translating SQL 'IN' subquery into a JPA Criteria Query

I'm trying to translate this SQL query into a JPA Criteria Query:
select distinct student0_.name
from vnic03.student student0_
where (exists(select teacher0_.social_number
from vnic03.teacher teacher0_
where teacher0.social_number = ?
and teacher0_.school_id in (select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id)))
These are the tables (I have simplified and renamed them for posting them here, in reallity they have several million entries):
Right now I have following code:
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<String> searchQuery = criteriaBuilder.createQuery(String.class);
Root<Student> root = searchQuery.from(Student.class);
List<Predicate> restrictions = new ArrayList<>();
Subquery<Teacher> subQuery = searchQuery.subquery(Teacher.class);
Root<Teacher> fromSchoolSubQuery = subQuery.from(Teacher.class);
List<Predicate> subRestrictions = new ArrayList<>();
Subquery<School> subQuery2 = searchQuery.subquery(School.class);
Root<School> fromSchoolSubSubQuery = subQuery2.from(School.class);
List<Predicate> subSubRestrictions = new ArrayList<>();
subRestrictions.add(criteriaBuilder.equal(fromSchoolSubQuery.get(Social_number), userInput));
subRestrictions.add(criteriaBuilder.equal(fromSchoolSubQuery.get(School_ID), subQuery2.select(fromSchoolSubSubQuery.get(School_ID)).where(criteriaBuilder.equal(fromSchoolSubSubQuery.get(Student_ID), root.get(student_ID)))));
restrictions.add(criteriaBuilder.exists(subQuery.select(
fromSchoolSubQuery.get(Social_number)).where(
subRestrictions.toArray(new Predicate[0]))));
searchQuery.distinct(true)
.select(root.get(name))
.where( restrictions.toArray(new Predicate[restrictions.size()]) );
TypedQuery<String> query = em.createQuery(searchQuery)
List<String> nameList = query.getResultList();
But this translates into:
select distinct student0_.name
from vnic03.student student0_
where (exists(select teacher0_.social_number
from vnic03.teacher teacher0_
where teacher0.social_number = ?
and teacher0_.school_id = (select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id)))
So I just need to replace the = by in in the last and part. I found in other SO questions something like this:
CriteriaBuilder.In<String> in = criteriaBuilder.in( ??? );
or
Path<Object> path = root.get(student_ID);
CriteriaBuilder.In<Object> in = criteriaBuilder.in(path);
but I just don't know how to use it properly...
So if you know how to translate only this part, it would solve it for me probably already:
where teacher0_.school_id **in** (select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id)))
I found a Solution after reading chapter 5 in this article: https://www.baeldung.com/jpa-criteria-api-in-expressions
Subquery<School> subQueryForInExpression = searchQuery.subquery(School.class);
Root<School> fromSchoolSubQuery = subQueryForInExpression.from(School.class);
subQueryForInExpression.select(fromSchoolSubQuery.get(student_id)).where(criteriaBuilder.equal(fromSchoolSubQuery.get(school_id), root.get(student_id)));
The subQueryForInExpression represents the Select subquery in the IN Expression:
select school0_.id
from vnic03.school school0_
where school0_.student_id = student0_.id
Now we have to add the in Expression to the subRestrictions, this is done with CriterisBuilder.in(...).value(subQueryForInExpression):
subRestrictions.add(criteriaBuilder.in(fromSchoolSubQuery.get(school_id)).value(subQueryForInExpression));

Build criteria query with joins and custom parameters

I need to build following query using JPA and criteria query but I stuck on join conditions. The query is:
SELECT p.*
FROM output cu
JOIN user ur ON cu.id = ur.id AND cu.key = ur.key
JOIN product p ON cu.id = p.id AND cu.key = p.key
WHERE p.refreshtimestamp IS NOT NULL AND cu.active = true
So far I have following, but how to apply join conditions:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Output> cq = cb.createQuery(Output.class);
Root<Output> output= cq.from(Output.class);
Join<Output, User> user = output.join("user", JoinType.INNER);
Join<User, Product> product = user.join("product", JoinType.INNER);
Any help will be appreciated
Following should help.
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> criteria = builder.createQuery(Product.class);
Root<Output> outputRoot = criteria.from(Output.class);
Root<User> userRoot = criteria.from(User.class);
Root<Product> productRoot = criteria.from(Product.class);
Predicate[] predictes = {
builder.equal(outputRoot.get("id"), userRoot.get("key")),
builder.equal(productRoot.get("id"), userRoot.get("key")),
builder.notEqual(productRoot.get("refreshtimestamp"), null), // not sure about null
builder.equal(outputRoot.get("active"), true)
};
criteria.select(productRoot);
criteria.where(builder.and(predicates));
Although this would produce cross joins query, it will work because of where clause making it work like inner join as you require.

In Hibernate 5, what's the CriteriaQuery equivalent of Criteria's restriction and projection?

Before Hibernate 5 deprecated the Criteria class, you could add restrictions to a Criteria to act as a constraint, and projections to act as select statements, like so
Criteria criteria = session.createCriteria(T.class)
.add(Restrictions.or(Restrictions.eq(property, constraintValue)
.set(Projection(Projections.projectionList()
.add(Projections.property(selectValue)));
But, since you now need to use CriteriaQuery like so,
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(T.class);
Root<T> root = criteriaQuery.from(T.class);
criteriaQuery.select(root);
Query<T> query = session.createQuery(criteriaQuery);
However I have been unable to figure out how to add certain things which are required in SQL statements, mainly because searching for documentation tends to wind up on documentation about Criteria, due to the naming similarity.
So, how can I recreate a simple query, like the one below, using CriteriaQuery?
SELECT selectValue
FROM tables.T
WHERE property = constraintValue
Source.
Has multiple examples, but turns out that the simple select statement we were trying to recreate can be done like so:
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<SELECTVALUETYPE> criteriaQuery = criteriaBuilder.createQuery(SELECTVALUETYPE.class);
Root<PARENTCLASS> root = criteriaQuery.from(PARENTCLASS.class);
criteriaQuery.select(root);
criteriaQuery.where(criteriaBuilder.equal(root.get(property), constraintValue));
Query<SELECTVALUETYPE> query = session.createQuery(criteriaQuery);
Note that this is a generic answer, and won't actually run. The reason being, SELECTVALUETYPE needs to be replaced with the data type of selectValue.
For example, CriteriaQuery might become:
String selectValue -> CriteriaQuery
T selectValue -> CriteriaQuery
Therefore, a working example for the statement
Select name
From Users
Where ID = 1
Could be expressed with the following block
int ID = 1;
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<String> criteriaQuery = criteriaBuilder.createQuery(String.class);
Root<User> root = criteriaQuery.from(User.class);
criteriaQuery.select(root.get("name");
criteriaQuery.where(criteriaBuilder.equal(root.get("ID"), ID));
Query<String> query = session.createQuery(criteriaQuery);
List<String>results = query.getResultList();
for(String name : results){
System.out.println("Name: " + name);
}

Convert this HQL to Criteria

I have the following HQL statement:
select auditRecord from AuditRecordEntity auditRecord where auditRecord.auditAccount.accountId = :accountId
I'd like to convert it to use the javax.persistence.criteria.CriteriaBuilder, but am unsure what do do, any help is much appreciated!
CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Object> query = builder.createQuery();
Root<AuditRecordEntity> root = query.from(AuditRecordEntity.class);
// what next?
Try this:
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<AuditRecordEntity> criteriaQuery = criteriaBuilder.createQuery(AuditRecordEntity.class);
Root<AuditRecordEntity> root = criteriaQuery.from(AuditRecordEntity.class);
Predicate predicate = criteriaBuilder.equal(root.get("auditAccount").get("accountId"), accountId);
criteriaQuery.where(predicate);
TypedQuery<AuditRecordEntity> query = em.createQuery(criteriaQuery);
return query.getSingleResult();
you can do it like following
public List<UserProfile> getAuditRecords(String acountId) {
Criteria auditCriteria = session.createCriteria(AuditRecordEntity.class);
auditCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
auditCriteria.createCriteria("auditAccount").add(Restrictions.eq("accountId ",acountId));
return auditCriteria .list();
}

JPQL: inner join with group by

I'm trying to retrieve data from database using criteriabuilder. It's working great, query is almost perfect... almost. Unfortunately Java don't want me to use group by or distinct as a result of my query. How to make Java retrieve only unique records? My code is here:
List<Documentation> documentationList = new ArrayList<>();
DatabaseConnector dc = new DatabaseConnector();
List<Predicate> criteria = new ArrayList<Predicate>();
EntityManager em = dc.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Documentation> select = builder.createQuery(Documentation.class);
Root<Documentation> u = select.from(Documentation.class);
Join<Documentation, DocumentationUser> du = u.join("documentationUserCollection", JoinType.INNER);
javax.persistence.Query q = em.createQuery(select);
select.groupBy(u.<String>get("documentationId"));
select.distinct(true);
documentationList = q.setMaxResults(pageSize).setFirstResult(first).getResultList();
Try swapping 2 lines lower the line that creates the query:
select.groupBy(u.<String>get("documentationId"));
select.distinct(true);
javax.persistence.Query q = em.createQuery(select);

Categories

Resources