如何将查询结果映射到除表格以外的实体?

4
我正在尝试从数据库中获取数据并将其映射到不同的实体,但是我遇到了问题。
java.lang.IllegalArgumentException: java.lang.ArrayIndexOutOfBoundsException: 0

我的表格看起来像这样:
@Entity
@Table(name = "Student")
@NamedNativeQueries({
    @NamedNativeQuery(name = "findAll", query = "Select a.student_id as id, a.student_code as code from Student a")
    })
public class Student {

    @Id
    private Long student_id;
    private String student_code;
    private String student_user_id;
    private String student_first_name;

    //Some other fields, getters and setters
}

我的BO长这样

@Entity
public class Generic{

    @Id
    private Long id;
    private String code;
    private String user_id;

    //getters and setters
}

我的DAO调用类大致如下

Query query = entityManager.createNamedQuery("findAll", Generic.class);
query.getResultList();

我遇到了异常

entityManager.createNamedQuery("findAll", Generic.class);

这是我拥有的堆栈跟踪:
    Caused by: java.lang.IllegalArgumentException: java.lang.ArrayIndexOutOfBoundsException: 0
at org.hibernate.internal.AbstractSharedSessionContract.buildQueryFromName(AbstractSharedSessionContract.java:774)
at org.hibernate.internal.AbstractSharedSessionContract.createNamedQuery(AbstractSharedSessionContract.java:869)
at org.hibernate.internal.AbstractSessionImpl.createNamedQuery(AbstractSessionImpl.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:301)
at com.sun.proxy.$Proxy157.createNamedQuery(Unknown Source)

请简要说明一下这个异常跟踪,你的POJO类中是否有一个构造函数接受这两个变量a.student_id作为id,a.student_code。 - Pandit Biradar
你正在使用哪个版本的 hibernate-orm - Shafin Mahmud
1个回答

2
我正在尝试从数据库中获取数据并将其映射到不同的实体,但我遇到了“ArrayIndexOutOfBoundsException”错误。
但在下一行中,您并没有这样做,而是尝试获取“Student”实体列表。这里的不同实体是什么?
entityManager.createNamedQuery("findAll", Student.class);
但是,由于您提供了另一个实体“Generic”,我假设您希望将数据加载到其中。有多种可能的解决方案。让我们找出来。
使用“SELECT NEW”关键字
将您的本地查询更新为以下内容:
@NamedNativeQueries({
    @NamedNativeQuery(name = "Student.findAll", query = "SELECT NEW Generic(a.student_id, a.student_code) FROM Student a")
})

你还需要在Generic类中定义一个构造函数,以便使这个调用合法。

public void Generic(Long id, String code) {
     this.id = id;
     this.code = code;
}

将DAO中的查询执行更新为:

List<Generic> results = em.createNamedQuery("Student.findAll" , Generic.class).getResultList();

注意: 您可能需要在查询中放置Generic类的完全限定路径

List<Object[]>构造

另一种简单直接的解决方案是将结果列表作为Object[]列表获取,并填充到任何您想要的新对象中。

List<Object[]> list = em.createQuery("SELECT s.student_id, s.student_code FROM Student s")
                        .getResultList(); 

for (Object[] obj : list){
    Generic generic = new Generic();
    generic.setId(((BigDecimal)obj[0]).longValue());
    generic.setCode((String)obj[1]);
}

我尝试过这个,但是我得到了一个异常,说Student.student_id是BigDecimal类型,而Generic.id是long类型。我能否在不改变数据类型的情况下进行类型转换? - Soumya
你实际上需要将它转换为 BigDecimal。请参考更新后的答案。 - Shafin Mahmud
有没有一种方法可以直接在命名本地查询中完成,我想避免使用对象。 - Soumya
你尝试过使用 SELECT NEW 的方法吗? - Shafin Mahmud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接