Результат собственного запроса EclipseLink в POJO - Отсутствует дескриптор для [Класс]
Я использую EclipseLink для запуска собственного Native SQL. Мне нужно вернуть данные в POJO. Я выполнил инструкции EclipseLink Docs, но получил ошибку Missing descriptor for [Class]
Столбцы запросов были названы в соответствии с переменными-членами POJO. Нужно ли делать какое-то дополнительное отображение?
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 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();
}
Ответы
Ответ 1
Я узнал, что вы можете поместить результаты выполнения Native Query в список массивов, содержащих объекты. Затем можно перебирать элементы списка и элементы массива и создавать нужные объекты Entity.
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);
}
Ответ 2
Старый вопрос, но может быть следующим решением, поможет кому-то другому.
Предположим, вы хотите вернуть список столбцов, тип данных и длину данных для данной таблицы в Oracle. Я написал ниже собственный пример запроса:
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";
Теперь необходимо создать список POJO из результата вышеуказанного запроса.
Определите класс сущности TableColumn
, как показано ниже:
@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();
}
}
Теперь мы готовы построить список POJO. Используйте приведенный ниже пример кода, чтобы построить результат в виде списка 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;
}
Ответ 3
Кроме того, не забудьте добавить в класс POJO в persistence.xml
! Это можно легко упускать из виду, если вы используете вашу среду IDE для управления этим файлом для вас.
Ответ 4
Вы можете использовать только собственные SQL-запросы с классом, если класс сопоставляется. Вы должны определить класс AnnouncementRecipientsFlattenedDTO как @Entity.
В противном случае просто создайте собственный запрос только с помощью SQL и получите массив данных и создайте свой DTO самостоятельно, используя данные.
Ответ 5
Имел ту же проблему, в которой я хотел вернуть список POJO, и на самом деле просто POJO (назовите его DTO, если хотите), а не аннотированные объекты @Entity.
class PojoExample {
String name;
@Enumerated(EnumType.STRING)
SomeEnum type;
public PojoExample(String name, SomeEnum type) {
this.name = name;
this.type = type;
}
}
Со следующим запросом:
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();
Создает PojoExample из базы данных без необходимости аннотации Entity на PojoExample. Вы можете найти вызов метода в Oracle Docs здесь.
изменить:
Как оказалось, для этого нужно использовать @SqlResultSetMapping, иначе ваш query.getResultList() возвращает список объектов.
@SqlResultSetMapping(name = "PojoExample",
classes = @ConstructorResult(columns = {
@ColumnResult(name = "name", type = String.class),
@ColumnResult(name = "type", type = String.class)
},
targetClass = PojoExample.class)
)
Просто поместите это где-нибудь под аннотация @Entity (так в этом примере либо в tablea, либо в tableb, потому что PojoExample не имеет аннотации @Entity)