Java 如何返回特定类型的列表而不是列表<;对象[]>;冬眠?

Java 如何返回特定类型的列表而不是列表<;对象[]>;冬眠?,java,hibernate,casting,hql,Java,Hibernate,Casting,Hql,我有三个班级: classA { classB b; classC c; ..... } 我有如下HQL查询: 选择a.field1、b.field2、c.field3、c.field4 从a.id=b.fk上的左侧外部连接b开始 b.id=c.fk上的左外连接c 此查询返回列表 是否可以将返回的数据强制转换为以下类: classD { Type1 fiedl1; Type2 field2; Type3 field3; }

我有三个班级:

classA {  
      classB b;  
      classC c;
      .....
} 
我有如下HQL查询:

选择a.field1、b.field2、c.field3、c.field4
从a.id=b.fk上的左侧外部连接b开始
b.id=c.fk上的左外连接c
此查询返回
列表

是否可以将返回的数据强制转换为以下类:

classD {
    Type1 fiedl1;
    Type2 field2;
    Type3 field3;
}

那么,可以通过Hibernate进行强制转换,还是我需要手动执行所有强制转换?

如果您确实确定可以执行类型强制转换

 List<classD> newlist = ...;
 for(Object o : list){
      newlist.add((classD) o);
 }
List newlist=。。。;
用于(对象o:列表){
添加((classD)o);
}
不过要小心

所以是的。手工铸造。(注意:对于数组(您可以直接强制转换))

您可以使用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(); 
TypedQuery q=em.createQuery(“从a.id=b.fk的左外连接b中选择a,b.id=c.fk的左外连接c”,ClassA.class);
List res=q.getResultList();

在JPA查询中有不同类型的选择您当前使用数组作为返回类型,您需要的是构造返回类型。以下是如何实现此目的:

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();
字符串查询器=
“选择新软件包。YourDefinedCustomClass(
a、 字段1,b.字段2,c.字段3,c.字段4)从左侧外部连接b
在a.id=b.fk上左外连接在b.id=c.fk上c”;
类型查询=
em.createQuery(queryStr,您定义的CustomClass.class);
List results=query.getResultList();
基本上有两件事:

  • 自定义类必须是结果返回类型
  • 自定义类必须有一个构造函数,该构造函数接受您在查询字符串中定义的结果值

  • 我也有同样的问题..我写了这个查询

    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");
    
    我返回了对象列表,在我编写的servlet中

    java.util.List objList=objFacultyService.listFaculty\u sql(1)

    java.util.List objtemp=new ArrayList();
    对于(对象[]对象:对象列表)
    {
    温度=新温度();
    temp.setFacultyEmailID(对象[3].toString());
    temp.setCourseName(对象[0].toString());
    if(对象[4]==null)
    {
    温度设置FacultyContactNo(1);
    }
    其他的
    {
    temp.setFacultyContactNo(Long.parseLong(objects[4].toString());
    }
    temp.setFacultyID(Long.parseLong(objects[1].toString());
    temp.setFacultyName(对象[2].toString());
    temp.setSubjectName(对象[5].toString());
    对象时间添加(温度);
    }
    
    如果您使用Hibernate 5.x,您可以使用
    ResultTransformer
    ,如所述。请注意,
    ResultTransformer
    将在Hibernate 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();
    
    List classDDTOs=entityManager
    .createQuery(
    “选择a.field1、b.field2、c.field3、c.field4”+
    “从a.id=b.fk上的左侧外部联接b”+
    “b.id=c.fk上的左外连接c”)
    .unwrap(org.hibernate.query.query.class)
    .setResultTransformer(
    新结果变压器(){
    @凌驾
    公共对象转换元组(
    对象[]元组,
    字符串[]别名){
    返回新类别D(
    (Type1)元组[0],
    (Type2)元组[1],
    (Type3)元组[1],
    );
    }
    @凌驾
    公共列表列表(列表集合){
    回收;
    }
    } 
    )
    .getResultList();
    
    上面的代码假设
    classD
    有一个构造函数
    classD(Type1,Type2,Type3)


    这种方法的一个优点是,它允许您定义一次
    ResultTransformer
    ,并允许您在具有相同结果类型的所有查询中重用它。

    从左外部联接中选择a,在a.id=b.fk上选择左外部联接c,在b.id=c.fk上选择左外部联接c
    这就是您要查找的吗?否。查询返回列表,但我想查询返回的列表不是列表类型的列表吗?我不明白,你的答案。这种返回类型只适用于单值选择。JPA文档说明:
    查询的select列表必须只包含单个项,该项必须可分配给resultClass参数指定的类型
    。hibernate的消息来源说,
    “无法使用请求的结果类型[“+resultClass.getName()+”]”为具有多个返回的查询创建TypedQuery
    。因此,基本上它将抛出IllegalArgumentException-如果发现查询字符串无效,或者如果发现查询结果无法分配给指定的类型,感谢您的准确回答!为了让答案更准确,我想指出构造函数名称必须是完全限定的,并且。我使用的是共享会话契约,所以我没有
    entityManager
    对象。无论如何要解决这个问题?哇,我要试试这个,但是hibernate 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();