EclipseLink native query result into POJO - Missing descriptor for [Class]

前端 未结 5 807
悲&欢浪女
悲&欢浪女 2020-12-17 10:18

I\'m using EclipseLink to run some Native SQL. I need to return the data into a POJO. I followed the instructions at EclipseLink Docs, but I receive the error Missing

相关标签:
5条回答
  • 2020-12-17 10:59

    I found out you can put the results of a Native Query execution into a List of Arrays that hold Objects. Then one can iterate over the list and Array elements and build the desired Entity objects.

    List<Object[]> rawResultList;
    
        Query query =
            em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT);
        rawResultList = query.getResultList();
    
        for (Object[] resultElement : rawResultList) {
            AnnouncementDeliveryLog adl = new AnnouncementDeliveryLog(getAnnouncementById(announcementId), (String)resultElement[1], (String)resultElement[2], "TO_SEND");
            persistAnnouncementDeliveryLog(adl);
        }
    
    0 讨论(0)
  • 2020-12-17 11:03

    You can only use native SQL queries with a class if the class is mapped. You need to define the AnnouncementRecipientsFlattenedDTO class as an @Entity.

    Otherwise just create the native query with only the SQL and get an array of the data back and construct your DTO yourself using the data.

    0 讨论(0)
  • 2020-12-17 11:16

    Also, don't forget to add in your POJO class in persistence.xml! It can be easy to overlook if you are used to your IDE managing that file for you.

    0 讨论(0)
  • 2020-12-17 11:23

    Old question but may be following solution will help someone else.

    Suppose you want to return a list of columns, data type and data length for a given table in Oracle. I have written below a native sample query for this:

      private static final String TABLE_COLUMNS = "select utc.COLUMN_NAME, utc.DATA_TYPE, utc.DATA_LENGTH "
            + "from user_tab_columns utc "
            + "where utc.table_name = ? "                
            + "order by utc.column_name asc";
    

    Now the requirement is to construct a list of POJO from the result of above query.

    Define TableColumn entity class as below:

    @Entity
    public class TableColumn implements Serializable {
    
    @Id
    @Column(name = "COLUMN_NAME")
    private String columnName;
    @Column(name = "DATA_TYPE")
    private String dataType;
    @Column(name = "DATA_LENGTH")
    private int dataLength;
    
    public String getColumnName() {
        return columnName;
    }
    
    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }
    
    public String getDataType() {
        return dataType;
    }
    
    public void setDataType(String dataType) {
        this.dataType = dataType;
    }
    
    public int getDataLength() {
        return dataLength;
    }
    
    public void setDataLength(int dataLength) {
        this.dataLength = dataLength;
    }
    
    public TableColumn(String columnName, String dataType, int dataLength) {
        this.columnName = columnName;
        this.dataType = dataType;
        this.dataLength = dataLength;
    }
    
    public TableColumn(String columnName) {
        this.columnName = columnName;
    }
    
    public TableColumn() {
    }
    
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (columnName != null ? columnName.hashCode() : 0);
        return hash;
    }
    
    @Override
    public boolean equals(Object object) {
    
        if (!(object instanceof TableColumn)) {
            return false;
        }
        TableColumn other = (TableColumn) object;
        if ((this.columnName == null && other.columnName != null) || (this.columnName != null && !this.columnName.equals(other.columnName))) {
            return false;
        }
        return true;
    }
    
    @Override
    public String toString() {
        return getColumnName();
    }
    
    }
    

    Now we are ready to construct a list of POJO. Use the sample code below to construct get your result as List of POJOs.

    public List<TableColumn> findTableColumns(String table) {
        List<TableColumn> listTables = new ArrayList<>();
        EntityManager em = emf.createEntityManager();
        Query q = em.createNativeQuery(TABLE_COLUMNS, TableColumn.class).setParameter(1, table);
        listTables = q.getResultList();
        em.close();
        return listTables;
    }
    
    0 讨论(0)
  • 2020-12-17 11:24

    Had the same kind of problem where I wanted to return a List of POJOs, and really just POJOs (call it DTO if you want) and not @Entity annotated Objects.

    class PojoExample {
    
      String name;
    
      @Enumerated(EnumType.STRING)
      SomeEnum type;
    
      public PojoExample(String name, SomeEnum type) {
        this.name = name;
        this.type = type;
      }
    }
    

    With the following Query:

    String query = "SELECT b.name, a.newtype as type FROM tablea a, tableb b where a.tableb_id = b_id";
    
    Query query = getEntityManager().createNativeQuery(query, "PojoExample");
    
    @SuppressWarnings("unchecked")
    List<PojoExample> data = query.getResultList();
    

    Creates the PojoExample from the database without the need for an Entity annotation on PojoExample. You can find the method call in the Oracle Docs here.

    edit: As it turns out you have to use @SqlResultSetMapping for this to work, otherwise your query.getResultList() returns a List of Object.

    @SqlResultSetMapping(name = "PojoExample", 
      classes = @ConstructorResult(columns = {
        @ColumnResult(name = "name", type = String.class), 
        @ColumnResult(name = "type", type = String.class)
      }, 
      targetClass = PojoExample.class)
     )
    

    Just put this anywhere under your @Entity annotation (so in this example either in tablea or tableb because PojoExample has no @Entity annotation)

    0 讨论(0)
提交回复
热议问题