I have a CriteriaBuilder and am trying to create a predicate to restrict results in a CollectionAttribute. I would like to say something like get all entities in this collection where the entity's attribute A equals x. For example, I have lots of People entities. They have a collection of job titles (previous and current) and I'd like to know about all people who have had a title of "banker". Here is an example:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Object> query = builder.createQuery();
Root<MheAreaLocation> root = query.from(MheAreaLocation.class);
Predicate p2 = builder.equal(root.get(Jobs_.jobs).get(Jobs_.titles), "banker");
TypedQuery<Object> q = em.createQuery(query);
List<Object> resultList = q.getResultList();
...
Any help would be great. I'm struggling to find much about CollectionAttribute and using them in predicates...and I keep getting nulls when I use the join below in the predicate :-( Thanks
This is my actual code:
CriteriaBuilder builder = em.getCriteriaBuilder();
// CriteriaQuery<Tuple> query = builder.createQuery();
CriteriaQuery<Object> query = builder.createQuery();
Root<MheAreaLocation> mheAreaLocationRoot = query.from(MheAreaLocation.class);
CollectionJoin<MheLocation, AtlasLocationGroupMap> join = mheAreaLocationRoot.join(MheAreaLocation_.childLocation).join(MheLocation_.atlasLocationGroupMapCollection);
// .join(AtlasLocationGroupMap_.atlasLocationGroup, JoinType.INNER);
Predicate p1 = builder.equal(mheAreaLocationRoot.get(MheAreaLocation_.parentLocation).get(MheLocation_.mheLocId), "AZP1B");
// Predicate p2 = builder.equal(mheAreaLocationRoot.get(MheAreaLocation_.childLocation).get(MheLocation_.atlasLocationGroupMapCollection).);
Predicate p2 = builder.equal(join.get(AtlasLocationGroupMap_.atlasLocationGroup).get(AtlasLocationGroup_.locationGroupType), "NEXT_STATION");
// query.where(builder.and(e1, e2));
// mheAreaLocationRoot.fetch(MheAreaLocation_.childLocation);
// join.fetch(MheLocation_.atlasLocationGroupMapCollection);
// query.multiselect(mheAreaLocationRoot.get(MheAreaLocation_.parentLocation),
// mheAreaLocationRoot.get(MheAreaLocation_.childLocation));
// query.select(builder.tuple(join.get(AtlasLocationGroupMap_.mheLocation)));
TypedQuery<Object> q = em.createQuery(query);
List<Object> resultList = q.getResultList();
...
Other classes (I can add more if needed):
#StaticMetamodel(MheLocation.class)
public class MheLocation_ {
public static volatile CollectionAttribute<MheLocation, AtlasLocationGroupMap> atlasLocationGroupMapCollection;
public static volatile SingularAttribute<MheLocation, String> mheLocId;
}
Take this example which has classes of Farm and Animal (Farm has a collection<Animal>) and we want to impose a criteria on the name of the Animal. Not exactly the same as yours I think, but may point you in the right direction
CriteriaBuilder qb = emf.getCriteriaBuilder();
CriteriaQuery<Farm> crit = qb.createQuery(Farm.class);
Root<Farm> candidate = crit.from(Farm.class);
candidate.alias("f");
crit.select(candidate);
Metamodel model = emf.getMetamodel();
ManagedType farmType = model.managedType(Farm.class);
Attribute animalAttr = farmType.getAttribute("animals");
Join animalJoin = candidate.join((ListAttribute)animalAttr);
animalJoin.alias("a");
Path nameField = animalJoin.get("name");
Predicate nameEquals = qb.equal(nameField, "Woolly Sheep");
crit.where(nameEquals);
Equates to
SELECT f FROM org.jpox.samples.annotations.one_many.bidir.Farm f JOIN f.animals a WHERE (a.name = 'Woolly Sheep')
HTH
Related
I'm trying to count the rows of the filter the user uses, when the user wants to list all it works fine, the problem is when they use filters and that makes some joins to work properly.
(This is used for a lazy datatable in jsf)
My criteria code is:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<CarreraHorizontal> cq = cb.createQuery(CarreraHorizontal.class);
Root<CarreraHorizontal> root = cq.from(CarreraHorizontal.class);
CriteriaQuery<Long> cqCount = cb.createQuery(Long.class);
List<Predicate> predicates = new ArrayList<Predicate>();
Join<CarreraHorizontal, Gdp> childJoin = root.join("gdp", JoinType.LEFT);
Join<CarreraHorizontal, Empleado> childJoin2 = root.join("empleado", JoinType.LEFT);
if (!StringUtils.isBlank(grupoTitulacion))
predicates.add(cb.like(root.<String>get("grupoTitulacion"), "%" + grupoTitulacion + "%"));
if(gdp0Bool) {
predicates.add(cb.like(childJoin.<String>get("nombre"), "GDP0"));
if(!StringUtils.isBlank(gdp0Combo))
predicates.add(cb.le(childJoin.<Integer>get("numEscalones"), Integer.parseInt(gdp0Combo)));
}
if(epg6) {
predicates.add(cb.equal(childJoin2.get("progresionEscalon"), epg6));
}
//cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
cqCount.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
Root<CarreraHorizontal> rootCount = cqCount.from(CarreraHorizontal.class);
CriteriaQuery<Long> a = cqCount.select(cb.count(rootCount));
TypedQuery<Long> res = em.createQuery(a.select(cb.count(rootCount)));
return res.getSingleResult();
My exception is:
Invalid path: 'generatedAlias1.progresionEscalon' [select count(generatedAlias0) from es.valencia.gp.sbch.entity.CarreraHorizontal as generatedAlias0 where generatedAlias1.progresionEscalon=:param0]
I tried everything I found but it's still not working.
Everywhere I look I see people using this
predicate =
criteriaBuilder.like(criteriaBuilder.lower(root.get(Product_.prodName)),
wrapper.getProdName());
especially I mean this Product_.prodName. I have no idea what it is, what it does and why I can't use or have it in my context. Here my code which not works:
Look at the line with !nachname.isEmpty
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Telefonbuch> query = builder.createQuery(Telefonbuch.class);
Root<Telefonbuch> root = query.from(Telefonbuch.class);
EntityType<Telefonbuch> model = em.getMetamodel().entity(Telefonbuch.class);
List<Predicate> predicates = new ArrayList<Predicate>();
if (!vorname.isEmpty()) {
Predicate condition = builder.like(root.<String>get("vorname"),"%"+vorname+"%");
predicates.add(condition);
}
if (!nachname.isEmpty()) {
Predicate condition = builder.like(builder.lower(root.get("nachname"),"%"+nachname+"%"));
predicates.add(condition);
}
query.select(root).where(predicates.toArray(new Predicate[predicates.size()]));
eintraege = em.createQuery(query).getResultList();
implementing pagination you can use criteria builder to return a page out of a result-set. However, if you need to get the full number of results (pages) you have to run a separate query with the same criteria for the count.
is there a way to combine the two together into single database call and save on performance without returning the full set and implement the page yourself?
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EntityJpa> cq = cb.createQuery(EntityJpa.class);
Root<EntityJpa> root = cq.from(EntityJpa.class);
Predicate p = cb.conjunction();
cq.where(p);
TypedQuery<EntityJpa> tq = em.createQuery(cq);
return tq.getResultList();
AND the count
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<EntityJpa> r = cq.from(EntityJpa.class);
Predicate p = cb.conjunction();
cq.where(p);
cq.select(cb.count(r));
TypedQuery<Long> tq = em.createQuery(cq);
return tq.getSingleResult().intValue();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
cq.select(cb.count(root)).where(pred).distinct(true);
Long maxPages = em.createQuery(cq).getSingleResult();
We Utilize something like this. I am working on a way to cache the results so I don't have to run the count every time it is paged, but this is working for us right now.
I am using JPA2.1 criteria API where in I have created a result object using criteria builder construct.
Consider the below sample piece of code.
CriteriaBuilder cb;//Assume cb is obtained here
CriteriaQuery<Report> cq = cb.createQuery(Report.class);// custom selective Class
Root<Student> root = cq.from(Student.class);
Join<Student, XTable> join1 = root.join("xtable", JoinType.INNER);
Join<Student, YTable> join1 = root.join("ytable", JoinType.INNER);
Below is the main line where I would select.
cq.select(cb.construct(Report.class,
root.get("name"), join1.get("address_type"), join2.get("country")));
Now, I would like to do a count on this construct Report.
I tried count like this.
cq.select(cb.count(cb.construct(......)));
// Failed because count accepts Expression and I tried assigning the cb.construct to Expression which is not working.
How to get the count?
I think it would look something like this:
Your code:
CriteriaBuilder cb;//Assume cb is obtained here
CriteriaQuery<Report> cq = cb.createQuery(Report.class);// custom selective Class
Root<Student> root = cq.from(Student.class);
Join<Student, XTable> join1 = root.join("xtable", JoinType.INNER);
Join<Student, YTable> join1 = root.join("ytable", JoinType.INNER);
countItemsByCriteria(entityManagerReference, cq, cb);
private <T> Long countItemsByCriteria(EntityManager em, CriteriaQuery<T> cqEntity, CriteriaBuilder cb) {
CriteriaBuilder builder = cb;
CriteriaQuery<Long> cqCount = builder.createQuery(Long.class);
Root<?> entityRoot = cqCount.from(cqEntity.getResultType());
cqCount.select(builder.count(entityRoot));
cqCount.where(cqEntity.getRestriction());
return em.createQuery(cqCount).getSingleResult();
}
As also described in this post: JPA + Hibernate count(*) using CriteriaBuilder - with generatedAlias
I need your help. Basically I want to create a custom query for a view I made that contains most of the data needed by the client. The tricky part here is that the client can specify which columns to include in the search. A sample query would be like:
SELECT distinct s.empno FROM SesdbAllView s
WHERE s.lastname IN :lname AND s.examTaken IN :exam AND
s.training IN :train AND s.trainingFrom BETWEEN :from AND :to AND
s.eligibility IN :elig AND s.profession IN :prof
So I tried translating this to Criteria API but still stuck on how to do it especially in the BETWEEN keywords (where I check a range of a Date and also another for a Integer). When it comes to the IN keywords I'm not sure if I did it correctly as well.
My current code now is:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<SesdbAllView> r = cq.from(SesdbAllView.class);
Predicate p = cb.conjunction();
for (Map.Entry<String, Object> param : parameters.entrySet()) {
if (param.getValue() instanceof List) {
Expression<String> exp = r.get(param.getKey());
p = cb.and(p, exp.in((List<String>)param.getValue()));
} else if (param.getValue() instanceof DateFromTo) {
DateFromTo fromTo = (DateFromTo) param.getValue();
p = cb.between(r.get(param.getKey()).as(Date.class),fromTo.getFrom(),fromTo.getTo());
} else if (param.getValue() instanceof IntegerFromTo) {
IntegerFromTo fromTo = (IntegerFromTo) param.getValue();
p = cb.between(r.get(param.getKey()).as(Integer.class),fromTo.getFrom(),fromTo.getTo());
} else {
p = cb.and(p, cb.equal(r.get(param.getKey()), param.getValue()));
}
}
cq.distinct(true);
cq.multiselect(r.get("empNo"))
.where(p);
List<Tuple> result = em.createQuery(cq).getResultList();