get a set of joined instances from a table using Criteria API - java

I have an entity PrintingFare
and a foreign key there - Printer,
so how do I use Criteria API that way so I get a set of Printers, which have Printing fares?
Basically I have a class PrintingFare with this field
#ManyToOne
#JoinColumn(name = "printer_id", foreignKey = #ForeignKey(name = "fk_fares_ref_printer_id"))
private Printer printer;
How do I get a set of Printers using Criteria API?

I haven't tested this, but you can try:
Criteria criteria = getSession().createCriteria(PrintingFare.class);
criteria.setProjection(Projections.distinct(Projections.property("printer"));
List<Printer> list = criteria.list();
Let me know if it works. It will probably have to be tweaked.

You should add restrictions to the query
Criteria criteria = getSession().createCriteria(PrintingFare.class);
criteria.add(Restrictions.eq("printer.id", printerId));
List<PrintingFare> list = criteria.list();
Criteria criteria = getSession().createCriteria(Printer.class);
criteria.createAlias("printerFairs", "pf").add(Restrictions.in("pf.id", printerFairIds));
List<Printer> list = criteria.list();

If PrinterFares is mapped from the Printer.class side ...
Criteria criteria = getSession().createCriteria(Printer.class);
criteria.createAlias("printerFares", "pf");
criteria.add(Restrictions.isNotEmpty("pf"));
crit.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List<Printer> printers = criteria.list();
If you are unable to change the mapping of Printer.class ...
Criteria criteria = getSession().createCriteria(Printer.class);
// create a subquery
DetachedCriteria dc = DetachedCriteria.forClass(PrinterFare.class);
dc.setProjection(Projections.property("printer.id"));
// restrict by subquery
criteria.add(Subqueries.in("id", dc);
crit.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List<Printer> printers = criteria.list();

Related

How to select only some fields using JPA criteria

I have a Student entity and want to select only two fields - id and age. After reading different posts I wrote the following code:
CriteriaQuery<Student> criteriaQuery = ..
var root = criteriaQuery.from(Student.class);
criteriaQuery.multiselect(root.get("id"), root.get("age"));
typedQuery = entityManager.createQuery(criteriaQuery);
List<Student> students = typedQuery.getResultList();
However, it doesn't work. How to do it using hibernate jpa provider?
If you only want two fields and use multiselect you can use a TupleQuery like in the example below:
CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
var root = criteriaQuery.from(Student.class);
criteriaQuery.multiselect(root.get("id"), root.get("age"));
typedQuery = entityManager.createQuery(criteriaQuery);
List<Tuple> students = typedQuery.getResultList();
To access the values of the tuples use the get method of it.
E.g.:
Long id = (Long) students.get(0).get(0);

Want to create dynamic mongo query to accept the DTO fields

I am creating a REST service using springboot and MONGO as database.
I have a StudentDTO class with the following fields :
Class StudentDTO{
#Id
int s_no;
String name;
String dept;
int dept_no;
String course;
//getter and setters
}
I have some criteria on which i need to fetch the data. These criteria may vary. Below are some example :
1. Can fetch data on name, dept
2. Can fetch data on name, id
3. May want data on name, dept and course. etc
There is no fixed combination of criteria on which I can build my query.
One of the solution which is not appropriate i try to write is :
Query query = new Query();
Criteria criteria = new Criteria().andOperator(
Criteria.where("id").is(Integer.parseInt(dto.getId()),
Criteria.where("name").is(dto.getName()),
Criteria.where("dept").exists(true).is(dto.getDept()),
Criteria.where("dept_no").is(dto.getDept_no()),
Criteria.where("course").is(dto.getSource()));
query.addCriteria(criteria);
List<StudentDTO> recordsList = mongoTemplate.find(query, StudentDTO.class, "student_collection");
In the above solution there is no accommodation for the scenario is any of the field is missing.
To check weather attribute exist or not i tried using the below query :
Criteria.where("id").exist(true).is(Integer.parseInt(dto.getId());
but how i can add criteria over the DTO fields.
You can use below code. Use orOperator which accepts the array of criteria. Prepare the criteria values dynamically inside if statements and add the criteria array to or criteria.
Query query = new Query();
Criteria criteria = new Criteria();
List<Criteria> orCriterias = new ArrayList<>();
if( dto.getId() != null) {
orCriterias.add(Criteria.where("id").is(Integer.parseInt(dto.getId())));
}
... so on for other fields
criteria.orOperator(orCriterias.toArray(new Criteria[orCriterias.size()]));
query.addCriteria(criteria);
List<StudentDTO> recordsList = mongoTemplate.find(query, StudentDTO.class, "student_collection");

Hibernate Criteria conditions or subqueries on OneToMany property values

One component of my application logs the parameters that an User send with an http URL. The mapping is as follow:
public class ActivityLog {
#Column(name = "id")
private Long id;
#OneToMany(mappedBy="activityLog", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
protected List<ActivityLogParameter> activityLogParameters = new ArrayList<ActivityLogParameter>();
}
public class ActivityLogParameter {
#Column(name = "id")
private Long id;
#Column(name = "key", length=10)
protected String key;
#Column(name = "value", length=50)
protected String value;
#ManyToOne(fetch = FetchType.LAZY, cascade={CascadeType.MERGE})
#JoinColumn(name="activity_log_id")
protected ActivityLog activityLog;
}
Let assume with every URL always 2 parameters are being passed: U and L
I need to create a query using hibernate's Criteria (mandatory from specification) so that it returns me all the ActivityLogs where both parameters matche a certain value. i.e.: U=aaa and L=bbb
I tried like this:
Criteria criteria = getCurrentSession().createCriteria(ActivityLog.class, "al");
// create alias
criteria = criteria.createAlias("activityLogParameters", "alp",JoinFragment.LEFT_OUTER_JOIN);
// create transformer to avoid duplicate results
criteria = criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteria = criteria.setFetchMode("al.activityLogParameters", FetchMode.SELECT);
//filters
criteria = criteria.add(Restrictions.or(Restrictions.eq("alp.value", UValue), Restrictions.ne("alp.key", "L")));
criteria = criteria.add(Restrictions.or(Restrictions.eq("alp.value", LValue), Restrictions.ne("alp.key", "U")));
But here I'm stuck. I tried to add projections like distinct and group by on this but it's not enough to have a correct result.
I'm trying also to use this criteria as a sub criteria, so to count the number of rows for any ActivityLog and keep only the records that have count(*) = 2 (all parameters match the condition) but I can't find how to do it with Subqueries.
Any idea on how to solve the above problem? In SQL I would do something like this:
select activity_log_id from (
select count(*) as ct, activity_log_id
from activity_log_parameter alp inner join activity_log al on alp.activity_log_id=al.id
where (alp.value='visitor' or alp.key<>'U')
and (alp.value='room1' or alp.key<>'L')
group by activity_log_id
) as subq
where subq.ct = 2
Thanks
Solved using a sub query
DetachedCriteria subquery = DetachedCriteria.forClass(ActivityLogParameter.class, "alp")
.createAlias("activityLog", "al",JoinFragment.LEFT_OUTER_JOIN)
.setProjection(Projections.projectionList()
.add(Projections.count("id"), "alpId"));
subquery = subquery.add( Property.forName("al.id").eqProperty("mainAl.id") );
subquery = subquery.add(Restrictions.or(Restrictions.eq("alp.value", UValue), Restrictions.ne("alp.key", "L")));
subquery = subquery.add(Restrictions.or(Restrictions.eq("alp.value", LValue), Restrictions.ne("alp.key", "U")));
Criteria criteria = getCurrentSession().createCriteria(type, "mainAl");
criteria = criteria.add(Subqueries.eq(new Long(2), subquery));

Converting the following criteria into SQL

I have the following criteria that I am using,..
List<boop> books =null;
Criteria criteria = session.createCriteria(boop.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("AAA"));
proList.add(Projections.property("BBB"));
RETURN criteria.list();
please advise how can I convert it in HQL..
Have a look at the Projections javadoc. Each Projections property corresponds to a database field.
select b.AAA, b.BBB
from boop b

How to join tables using hibernate criteria

I am trying to join multiple table to join using criteria but getting error in doing so can someone please help me in it
My code is
final Session session = getSession();
final Criteria criteria = session.createCriteria(ReferralPaymentInfo.class).createCriteria("SIGNUP_REFERRAL");
System.out.println("before");
List list = criteria.list();
System.out.println("after");
I also tried this code
final Session session = getSession();
final Criteria criteria =session.createCriteria(ReferralPaymentInfo.class);
criteria.setFetchMode("SIGNUP_REFERRAL", FetchMode.JOIN);
List list = criteria.list();
This gives result only from table ReferralPaymentInfo and not considering table SIGNUP_REFERRAL
Can some one please help me out
T
try this
DetachedCriteria ownerCriteria = DetachedCriteria.forClass(Owner.class);
ownerCriteria.setProjection(Property.forName("id"));
ownerCriteria.add(Restrictions.eq("ownername", "name"));
Criteria criteria = getSession().createCriteria(Pet.class);
criteria.add(Property.forName("ownerId").in(ownerCriteria));

Categories