2013-02-25 11 views
10

Utilizzo EclipseLink per eseguire alcuni SQL nativi. Devo restituire i dati in un POJO. Ho seguito le istruzioni allo EclipseLink Docs, ma ricevo l'errore Missing descriptor for [Class]Risultato query nativa EclipseLink in POJO: descrittore mancante per [Classe]

Le colonne della query sono state denominate per corrispondere alle variabili membro del POJO. Devo fare qualche mappatura aggiuntiva?

POJO:

public class AnnouncementRecipientsFlattenedDTO { 

     private BigDecimal announcementId; 
     private String recipientAddress; 
     private String type; 

     public AnnouncementRecipientsFlattenedDTO() { 
      super(); 
     } 

     public AnnouncementRecipientsFlattenedDTO(BigDecimal announcementId, String recipientAddress, String type) { 
      super(); 
      this.announcementId = announcementId; 
      this.recipientAddress = recipientAddress; 
      this.type = type; 
     } 

    ... Getters/Setters 

Entity Call Manager:

public List<AnnouncementRecipientsFlattenedDTO> getNormalizedRecipientsForAnnouncement(int announcementId) { 
    Query query = em.createNamedQuery(AnnouncementDeliveryLog.FIND_NORMALIZED_RECIPIENTS_FOR_ANNOUNCEMENT, AnnouncementRecipientsFlattenedDTO.class); 
    query.setParameter(1, announcementId); 
    return query.getResultList(); 
} 

risposta

9

Ho scoperto che è possibile inserire i risultati di un'esecuzione di Query nativa in un elenco di matrici che contengono oggetti. Quindi si può scorrere l'elenco e gli elementi dell'array e creare gli oggetti entità desiderati.

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); 
    } 
5

È possibile utilizzare solo le query SQL nativo con una classe se la classe è mappata. È necessario definire la classe AnnouncementRecipientsFlattenedDTO come @Entity.

Altrimenti basta creare la query nativa con solo l'SQL e recuperare una serie di dati e costruire il DTO da solo utilizzando i dati.

+0

Condivide l'Entity devono essere associati a un tavolo o può essere libero? – retrodev

+0

Sicuramente questa è la risposta per risolvere il problema. Nel caso in cui si desideri mappare su DTO, è possibile utilizzare @SqlResultSetMapping –

8

Vecchia domanda, ma potrebbe essere la seguente soluzione aiuterà qualcun altro.

Supponiamo di voler restituire un elenco di colonne, tipo di dati e lunghezza dati per una data tabella in Oracle. Ho scritto di sotto di una query di esempio nativo per questo:

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"; 

Ora l'esigenza è quella di costruire un elenco di POJO dal risultato di sopra della query.

Definire TableColumn classe entità, come di seguito:

@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(); 
} 

} 

ora siamo pronti a costruire una lista di POJO. Utilizzare il seguente codice di esempio per costruire ottenere il risultato come Elenco di POJO.

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; 
} 
+1

Ciò crea una nuova tabella nel DB denominata TableColumn. Qualche altra soluzione? – scarface

6

Inoltre, non dimenticare di aggiungere la classe POJO in persistence.xml! Può essere facile trascurare se sei abituato all'IDE che gestisce quel file per te.

2

Avevo lo stesso tipo di problema in cui volevo restituire un elenco di POJO, e in realtà solo POJO (chiamalo DTO se vuoi) e non oggetti annotati da @Entity.

class PojoExample { 

    String name; 

    @Enumerated(EnumType.STRING) 
    SomeEnum type; 

    public PojoExample(String name, SomeEnum type) { 
    this.name = name; 
    this.type = type; 
    } 
} 

Con la seguente 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(); 

Crea il PojoExample dal database senza la necessità di un'annotazione sulla entità PojoExample. È possibile trovare la chiamata al metodo nello Oracle Docs here.

modifica: In base alle esigenze, è necessario utilizzare @SqlResultSetMapping affinché funzioni, altrimenti query.getResultList() restituisce un elenco di oggetti.

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

Basta mettere questo ovunque sotto la vostra annotazione @Entity (quindi in questo esempio sia in TableA o TableB perché PojoExample ha alcuna annotazione @Entity)

Problemi correlati