Filter using field from child entity - java

I have class Person containing field age, Class Student extends Person containing field class, and class Teacher extends Person and containing field salary.
I want to get all Person who are in class X, if they are Student, and earn 1500$, if they are Teacher, using the same jpql query. The query must return a list of Person. I can make two query and make a method that call both query and join the result but is there a better solution.
I hope I was able to explain

Use "TYPE" and JPA 2.1 "TREAT" to filter on the class.
"SELECT p from Person p where treat(p as Teacher).salary = 1500 or TYPE(p) = Student"
If you cannot use JPA 2.1, you can use a subquery on Teacher to return Teacher ids with salary=1500, and use the result in the main query.
"SELECT p from Person p where p.id in(SELECT t.id from Teacher t where t.salary=1500) or TYPE(p) = Student"

Related

Spring Data JPA : How to write subquery having IN operator

I am a new to Spring Data JPA, wanted to know how do I write the following subquery:
select o from Owner o where o.ownerId IN (Select c.ownerId from Cars c)
Here Owner is one entity class and Cars is another entity class and I'll be having two repositories one as OwnerRepository and the other as CarRepository, both extending JPARepository.
Help needed in writing this sort of custom queries with IN operator.
Thanks in advance.
You could always just use your query as a custom query:
#Query(value = "select o from Owner o where o.ownerId IN (Select c.ownerId from Cars c")
Owner getOwner();
If you need to pass variables to the query, use the #Param tag, like so:
#Query(value = "SELECT * FROM Owner o WHERE o.ownerId = :id")
Owner getOwnerWithId(#Param("id") Long id);

Hibernate criteria query multiple criteria

In my current project I've faced a problem of getting entities with hibernate criteria query. I have the following entities:
Professor, which contains a list of students
Student, which contains a list of assignments.
Assignment, which contains id of student to which it is assigned to.
Now, I want to get all assignments relative to the professor, i.e. all assignments Professor assigned to his students.
This query shows what I want to implement in criteria query.
select * from Assigment p, Student a, Professor c where p.studentid = a.id and a.proffid = c.id and c.id = 2411;
How can I implement this query using hibernate criteria API?
suppose your tables like that:
#Entity
public class Professor{
K id;
List<Student> students;
}
#Entity
public class Student{
K profid;
List<Assignments> assignments;
}
#Entity
public class Assignments{
K studentid;
}
simple sample by using alias:
Criteria criteria = currentSession.createCriteria(Professor.class, "professor");
criteria.createAlias("professor.students", "student");
criteria.createAlias("student.assigments", "assigment");
criteria.add(Restrictions.eqProperty("professor.id", "student.profid"));
criteria.add(Restrictions.eqProperty("assigment.studentid", "student.profid"));
criteria.add(Restrictions.eq("id", 2411));
return criteria.list();

How to create a JPA query with LEFT OUTER JOIN

I am starting to learn JPA, and have implemented an example with JPA query, based on the following native SQL that I tested in SQL Server:
SELECT f.StudentID, f.Name, f.Age, f.Class1, f.Class2
FROM Student f
LEFT OUTER JOIN ClassTbl s ON s.ClassID = f.Class1 OR s.ClassID = f.Class2
WHERE s.ClassName = 'abc'
From the above SQL I have constructed the following JPQL query:
SELECT f FROM Student f LEFT JOIN f.Class1 s;
As you can see, I still lack the condition OR s.ClassID = f.Class2 from my original query. My question is, how can I put it into my JPQL?
Write this;
SELECT f from Student f LEFT JOIN f.classTbls s WHERE s.ClassName = 'abc'
Because your Student entity has One To Many relationship with ClassTbl entity.
If you have entities A and B without any relation between them and there is strictly 0 or 1 B for each A, you could do:
select a, (select b from B b where b.joinProperty = a.joinProperty) from A a
This would give you an Object[]{a,b} for a single result or List<Object[]{a,b}> for multiple results.
Normally the ON clause comes from the mapping's join columns, but the JPA 2.1 draft allows for additional conditions in a new ON clause.
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#ON
Please see :
public interface YourDBRepository extends JpaRepository<Employee, Long> {
#Query("select new com.mypackage.myDTO(dep.empCode, dep.empName, em.EmployeeCode, em.EmployeeName) \n" +
"from Department dep\n" +
"left join Employee em\n" +
"on dep.DepartmentCode = em.DepartmentCode") // this is JPQL so use classnames
List<myDTO> getDeptEmployeeList();
}
You can also use CrudRepository and include #JoinColumn with FK table class in PK table class and have List return list and then do find operation to achieve the same.
In Department entity class:
#OneToMany
#Fetch(FetchMode.JOIN)
#JoinColumn(name="DEPT_CODE")
private List<Employee> employees;
CriteriaBuilder is yet another option.

JPA CriteriaQuery OneToMany

I have two entities with a OneToMany relationship. To make it simple, let's suppose them as School and Students, with a unidirectional relationship from school to students. I want to find the school object that has a specific student (a student with a specific age, name, ssn, ...).
I know that I can create a simple criteria as the following for simple School's properties (for School's name, as the following):
ParameterExpression<String> p = criteriaBuilder.parameter(String.class, "schoolName");
criteria = criteriaBuilder.and(criteria, criteriaBuilder.like(schoolRoot.get("schoolName") , p));
queryResult.setParameter("schoolName", schoolName + "%");
but, how can I query students with a specific property value while the students is represented as a java.util.List instead of being a basic property?
Can somebody can help me figure this out? I hope I have been able to explain my problem.
Thanks
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<School> query = criteriaBuilder.createQuery(School.class);
Root<School> schoolRoot = query.from(School.class);
Join<School, Student> join = schoolRoot.join(School_.students);
query.where(criteriaBuilder.equal(join.get(Student_.name), "john"));
It looks up a student with name john in all schools.
I guess that would do the similar thing;
FROM School sch WHERE 'Student Name' = ANY (SELECT stud.name FROM sch.students stud)

How to get the most occured set of objects?

I have two objects.
#Entity
class Person extends Model {
...
#OneToOne
Category category;
}
#Entity
class Category extends Model {
...
}
I need to get the 5 most used categories. How can I do that ?
Thanks,
EDIT : Solution
List<Object[]> c = Category.find(
"SELECT p.categorie, count(p.id) FROM Person p " +
"GROUP BY p.category ORDER BY count(p.category) DESC").fetch(2);
Your JPQL query would be something like this:
SELECT p.category, COUNT(p.category)
FROM Person p
GROUP BY p.category
ORDER BY count(p.category) DESC
And you'd do query.setMaxResults(5) also.
select category.id, count(person.id)
from Person person
inner join person.category category
group by category.id
order by count(person.id) desc
And before executing this query, call setMaxResults(5) on the Query object.

Categories