【问题标题】:How can I map the result set of query to a different entity other than table如何将查询结果集映射到表以外的其他实体
【发布时间】:2020-01-28 05:25:31
【问题描述】:

我正在尝试从数据库中获取数据并将其映射到不同的实体,但我得到了

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 的构造函数
  • 您使用的是哪个hibernate-orm 版本?

标签: java hibernate jpa spring-data-jpa


【解决方案1】:

我正在尝试从 db 中获取数据并将其映射到不同的实体 但我得到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 类的完全限定路径放在 Query 中

List&lt;Object[]&gt;构造

或者,直接和最简单的解决方案是将结果列表作为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 很长。我可以在不更改数据类型的情况下进行类型转换吗?
  • 您实际上需要将其转换为BigDecimal。查看更新的答案
  • 有没有办法直接在命名原生查询中做,我避免使用对象
  • 您尝试过SELECT NEW 方法吗?
猜你喜欢
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
相关资源
最近更新 更多