I am trying to write a query in HQL but it doesn't work. The query filters Students by Grades. Grade is a ManyToMany list inside Student's class.
Exapmle (Student.java):
#NamedQuery(name = "getStudentsByGrade" , query = "from Student where :grade in grades")
The Student class has list property:
Private List<Grade> grades;
This :grade member of grades was what i looked for.
Related
In this scenario rather than doing complete select on object,have decided to go for select statement on fields required only.Hence the queries generated will be less.
Once the result is in,i want to cast back to original values and return them to calling method.
Please suggest any alternative efficient approach.
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
#Column(name="enroll_id")
private String enrollmentId;
public Student(Integer id, String enrollmentId) {
super();
this.id = id;
this.enrollmentId = enrollmentId;
}
// source code continues
}
public List<Student> getStudentList(){
Query multipleSelect=em.createQuery("select student.id,student.enrollmentId from Student as student");
List<Object[]> studentList=multipleSelect.getResultList();
List<Student> studentArrayList=new ArrayList<Student>();
for(Object[] list:studentList){
Integer id=((Integer)list[0]);
String eId=((String)list[1]);
studentArrayList.add(new Student(id, eId));
}
return studentArrayList;
}
If you're asking for a way to avoid casting each row from the resultList and having to manually create Student object then try using "JPQL Constructor Expressions"
You're select query can be modified as:
"select NEW com.FullyQualifiedName.Student(student.id,student.enrollmentId) from Student as student"
and accept the query result directly as
List<Student> studentList=multipleSelect.getResultList();
or Simply:
public List<Student> getStudentList(){
return em.createQuery("select NEW com.FullyQualifiedName.Student(student.id,student.enrollmentId) from Student as student").getResultList();
}
Note:
Make sure Student constructor is called using fully qualified name.
Do not use JPQL with createNativeQuery.
If you want the output of the query to be of Student type then you'll have to create the query in a different way, i.e.,
TypedQuery<Student> multipleSelect=em.createQuery("select NEW your_package.Student(student.id,student.enrollmentId) from Student as student"
, Student.class);
List<Student> students = multipleSelect.getResultList();
However, this is not a good way to do this as the return type of the method would suggest that it is returning a completely filled Student object. Also, you'll have to make constructors for every combination. I would rather suggest you fetch a map, i.e.,
TypedQuery<Map> multipleSelect=em.createQuery("select NEW map(student.id as id,student.enrollmentId as eid) from Student as student"
, Map.class);
List<Map> students = multipleSelect.getResultList();
This will return you a map with key as "id" and value as the actual id of the student.
Here is the overview of a problem..
public class Student
{
private Map<Test,MarkWrapper> marks;
...
}
public class MarkWrapper
{
private List<Mark> marks;
...
}
public class Test
{
private String name;
private Date date;
..
}
public class Mark
{
private int mark;
private int total;
private float average;
...
}
Now, I would like to retrieve students who got 90 marks. Rather than changing the architecture by removing the map, how to solve this problem?
In the Map class there is no getter method to get the values in it. If this can't be achieved then how would i do it with Criteria API?
Thank you.
I would like to retrieve students who got 90 marks
If you want to retrieve student whose marks is exact 90 then make your map key as 90 and add value as student.
Example:
Pun on map to those students who got exact 90 marks by iterating studentList
Map<Integer,Student> studentMap=new HashMap<Integer, Student>();
List<Student> studentList= <yourStudentList>;
for(Student student : studentList){
if(student.getMarks() == 90){
studentMap.put(90,student);
}
}
Edit:
I assume you have entity class name as Student and have property marks and so on.
Using JPQL:
You can do to get students list from database either
String jpql="Select s from Student s where s.marks =:marks ";
Query query=em.createQuery(jpql);
query.setParameter("marks", 90);
List<Student> studentList=query.getResultList();//returns all students who got marks 90
or
String jpql="Select s from Student s ";
Query query=em.createQuery(jpql);
List<Student> studentList1=query.getResultList();//returns all students
and you can put in map to all students who got 90 marks by iterating studentList1 like I said earlier
An example JPQL query string:
SELECT s FROM Student s JOIN s.marks sm
WHERE VALUE(sm) IN (
SELECT mw FROM MarkWrapper mw JOIN mw.marks mwm
WHERE mwm.mark = :value
)
where :value is query parameter (i.e. 90)
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"
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();
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)