I need to convert a Hibernate criteria query like the following
curList = session.createCriteria(Islem.class)
.createAlias("workingDay", "d")
.setProjection(Projections.sum("amount"))
.add(Restrictions.eq("currency", CURRENCY))
.add(Restrictions.eq("product", product))
.add(Restrictions.ne("status", INACTIVE))
.add(Restrictions.eq("d.status", ACTIVE))
.getResultList();
However in JPA (2) I have no idea how to implement the projection - in this case - the sum. It's odd that Hibernate and JPA (even Hibernate JPA 2) have this tremendous differences especially in criteria queries.
I start by
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Islem> cq = cb.createQuery(Islem.class);
Root<Islem> isr = cq.from(Islem.class);
cq.select(isr).where(cb.equal(isr.get("currency"), CURRENCY),
cb.notEqual(isr.get("status"), INACTIVE),
cb.equal(isr.get("product"), product));
however have no idea how to implement the projection here neither the alias
Projection is one of the first things you're probably thinking about when implementing a query with Spring Data JPA. This is because projection defines the entity attributes and the database columns returned by your query. So, selecting the right columns is important for your business logic.
A DTO projection is a Java Object that contains the column values that were fetched by a given SQL projection query. The DTO projection can be a POJO (Plain Old Java Object), a JPA Tuple , or a Java Record, and we can fetch all those DTO projection types using Spring Data JPA.
To put it simple, Hibernate Projections are used in order to query only a subset of the attributes of an entity or group of entities you're querying with Criteria. You can also use Projections to specify distinct clauses and aggregate functions like max , sum and so on.
Fetching a one-to-many DTO projection with JPA and Hibernate. The postDTOMap is where we are going to store all PostDTO entities that, in the end, will be returned by the query execution. The reason we are using the postDTOMap is that the parent rows are duplicated in the SQL query result set for each child record.
It's an old question, but let's give an example:
With CriteriaBuilder
, unlike Hibernate, you always start off with the type of the result you want to query and then construct the projection.
CriteriaBuilder cb = em.getCriteriaBuilder();
//We want Integer result
CriteriaQuery<Integer> cq = cb.createQuery(Integer.class);
//The root does not need to match the type of the result of the query!
Root<Islem> isr = cq.from(Islem.class);
//Create a join to access the variable status of working day
Join<Islem,WorkingDay> join = isr.join("workingDay",JoinType.INNER);
//Create the sum expression
Expression<Integer> sum = cb.sum(isr.get("amount"));
cq.where(
cb.equal(isr.get("currency"), CURRENCY),
cb.notEqual(isr.get("status"), INACTIVE),
cb.equal(isr.get("product"), product),
cb.equal(join.get("status"), ACTIVE)
).select(sum);
On the other hand if you wanted to query for the actual "amount" values, you could do:
CompoundSelection<Integer> projection = cb.construct(Integer.class, cb.sum(isr.get("amount")));
cq.where(..).select(projection);
List<Integer> amounts = em.createQuery(cq).getResultList();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With