Как мы можем отобразить сложные результаты NativeQuery на объекты DTO, используя Java - PullRequest
0 голосов
/ 11 апреля 2019
Query query = em.createNativeQuery(STUDENT_QUERY_WITH_PARAMS);
        query.setParameter("studentId", stduentId);
        query.setParameter("startDate", valueOf(startDate), TemporalType.DATE);
        query.setParameter("endDate", valueOf(endDate), TemporalType.DATE);
        List<Object[]> resultList = query.getResultList();

        List<StudentDepartmentCatDTO> result = new ArrayList<>(resultList.size());
        for (Object[] row : resultList) {
            result.add(new StudentDepartmentCatDTO((String)row[0], (String)row[1], (String)row[2], null,(UUID)row[4], (Integer)row[5], (Integer)row[6], (Integer)row[7], (Integer)row[8], null, null, null, null ));
        }

`У меня есть SQL-запрос для извлечения определенных данных из различных таблиц путем объединения нескольких таблиц (в моем случае 13 таблиц), и я могу вернуть все результаты успешно, но когда я пытаюсь отобразить эти результаты обратнов DTO я получаю исключения.Как мне преодолеть эти исключения?

B нельзя привести к классу java.util.UUID и классу java.math.BigDecimal нельзя привести к классу java.lang.Integer

, так как всерезультаты поступают из разных таблиц, я не нашел способа сделать это с помощью SqlResultSetMapping, поскольку ни один из управляемых объектов не может быть напрямую сопоставлен с результатами.Есть лучший способ сделать это?а я как исправить эти исключения броска?Могу ли я создать неуправляемую сущность, чтобы сопоставить с ней все результаты?Как извлечь результаты sql в мой DTO.

1 Ответ

1 голос
/ 11 апреля 2019

Вы можете использовать @SqlResultSetMapping для преобразования каждой записи в вашем наборе результатов в объект DTO .Но для этого потребуется дополнительный конструктор, чтобы вам не нужно было устанавливать какие-либо параметры на null.

. Вот пример такого отображения.Как видите, вам нужно ссылаться на элементы в вашем наборе результатов по их имени, но вы не поделились своим запросом.Поэтому я не могу адаптировать пример к вашему запросу.

@SqlResultSetMapping(
        name = "BookValueMapping",
        classes = @ConstructorResult(
                targetClass = BookValue.class,
                columns = {
                    @ColumnResult(name = "id", type = Long.class),
                    @ColumnResult(name = "title"),
                    @ColumnResult(name = "version", type = Long.class),
                    @ColumnResult(name = "authorName")}))

Я использую это сопоставление с запросом, который выбирает столбцы id, title, version и authorName избаза данных.Аннотация @ConstructorResult описывает вызов конструктора класса BookValue.Аннотации @ColumnResult определяют параметры конструктора и их порядок.Необходимо убедиться, что созданный экземпляр класса предоставляет конструктор, который соответствует этим параметрам.

@SqlResultSetMapping - мощная и гибкая функция в JPA.Я объясню это очень подробно здесь: https://thoughts -on-java.org / result-set-mapping-constructor-result-mappings /


ОК, теперь давайте возьмемвзгляните на проблему приведения класса ...

Приведение не удалось, потому что два объекта имеют неправильный класс.row[4] кажется byte[], а один из row[6/7/8] (или все они) представляется BigInteger.

Этот фрагмент кода должен помочь вам преобразовать байт [] в UUID:

ByteBuffer bb = ByteBuffer.wrap(bytes);
long high = bb.getLong();
long low = bb.getLong();
UUID uuid = new UUID(high, low);

Преобразование BigDecimal в Integer намного проще.Вам просто нужно вызвать метод intValueExact() на вашем BigDecimal, например, row[6].intValueExact();.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...