Как вернуть список определенного типа вместо списка в Hibernate?
у меня есть дерево классов:
classA {
classB b;
classC c;
.....
}
у меня есть запрос HQL, как это:
SELECT a.field1, b.field2, c.field3, c.field4
FROM a LEFT OUTER JOIN b ON a.id = b.fk
LEFT OUTER JOIN c ON b.id = c.fk
этот запрос возвращает List<Object[]>
.
можно ли привести возвращаемые данные к следующему классу:
classD {
Type1 fiedl1;
Type2 field2;
Type3 field3;
}
так может ли кастинг быть сделан Hibernate или мне нужно вручную сделать все кастинг?
5 ответов
существуют различные типы выбора в запросах JPA. В настоящее время вы используете Array как тип возврата, вам нужно построить тип возврата. вот как этого добиться:
String queryStr =
"select NEW package.YourDefinedCustomClass(
a.field1, b.field2, c.field3, c.field4) from a left outer join b
on a.id=b.fk left outer join c on b.id=c.fk";
TypedQuery<YourDefinedCustomClass> query =
em.createQuery(queryStr, YourDefinedCustomClass.class);
List<YourDefinedCustomClass> results = query.getResultList();
в основном есть две вещи:
- пользовательский класс должен быть вашим типом возврата результатов
- пользовательский класс должен иметь конструктор, который принимает значения результатов, определенные в строке запроса.
вы можете использовать TypedQuery
TypedQuery<ClassA> q = em.createQuery("select a from a left outer join b on a.id=b.fk left outer join c on b.id=c.fk", ClassA.class);
List<ClassA> res = q.getResultList();
Если вы действительно уверены, что вы можете делать приведения типов.
List<classD> newlist = ...;
for(Object o : list){
newlist.add((classD) o);
}
будьте осторожны с этим, хотя
да. Ручное литье. (примечание: с массивами (вы можете напрямую бросить))
у меня была такая же проблема..я написал этот запрос
Query sqlquery = session.createQuery("select c.courseName,f.facultyID,f.facultyName,f.facultyEmailID,f.facultyContactNo,s.subjectName from com.bean.CourseBean as c,com.bean.FacultyBean as f,com.bean.Faculty_SubjectBean as fs,com.bean.SubjectBean as s where f.facultyID=fs.facultyBean.facultyID AND s.subjectID=fs.subjectBean.subjectID AND c.courseID=f.courseBean.courseID AND collegeid=1");
и я вернул список объекта и в сервлете написал,
java.утиль.Список objList= objFacultyService.listFaculty_sql(1);
java.util.List<Temp> objtemp = new ArrayList<Temp>() ;
for (Object[] objects : objList)
{
Temp temp = new Temp();
temp.setFacultyEmailID(objects[3].toString());
temp.setCourseName(objects[0].toString());
if(objects[4]==null)
{
temp.setFacultyContactNo(1);
}
else
{
temp.setFacultyContactNo(Long.parseLong(objects[4].toString()));
}
temp.setFacultyID(Long.parseLong(objects[1].toString()));
temp.setFacultyName(objects[2].toString());
temp.setSubjectName(objects[5].toString());
objtemp.add(temp);
}
если вы используете Hibernate 5.X, вы можете использовать ResultTransformer
, как, например, описано в этой статье. Обратите внимание, что ResultTransformer
будет @Deprecated в спящем режиме 6.
применяется к вашему сценарию:
List<classD> classDDTOs = entityManager
.createQuery(
"SELECT a.field1, b.field2, c.field3, c.field4 " +
"FROM a LEFT OUTER JOIN b ON a.id = b.fk " +
"LEFT OUTER JOIN c ON b.id = c.fk")
.unwrap( org.hibernate.query.Query.class )
.setResultTransformer(
new ResultTransformer() {
@Override
public Object transformTuple(
Object[] tuple,
String[] aliases) {
return new classD(
(Type1) tuple[0],
(Type2) tuple[1],
(Type3) tuple[1],
);
}
@Override
public List transformList(List collection) {
return collection;
}
}
)
.getResultList();
приведенный выше код предполагает classD
имеет конструктор classD(Type1, Type2, Type3)
.
преимуществом этого подхода является то, что он позволяет определить ResultTransformer
раз и позволяет использовать его во всех запросах с тем же типом результата.