org.postgresql.util.PSQLException: ОШИБКА: оператор не существует: целое число = bytea - PullRequest
1 голос
/ 08 октября 2019

Я пытаюсь выполнить собственный запрос из приложения Spring Boot, но я получаю эту ошибку "org.postgresql.util.PSQLException: ОШИБКА: оператор не существует: integer = bytea"

Здесьэто коды, которые я написал для реализации этого

  @SqlResultSetMapping(
    name = "StudentAssessmentValue",
    classes = @ConstructorResult(
            targetClass = StudentAssessmentDTO.class,
            columns = {
                    @ColumnResult(name = "subject_title", type = String.class),
                    @ColumnResult(name = "assessment", type = String.class),
            }
    )
  )


  @NamedNativeQuery(
                    name = "getStudentSubjectsAssessment",
                    query = "SELECT\n" +
                            "   subject.subject_title,\n" +
                            "   j as assessment\n" +
                            "FROM   assessment s\n" +
                            "JOIN   LATERAL jsonb_array_elements(s.assessment) j(elem) ON (j.elem->>'student_id') = :student_id\n" +
                            "JOIN subject ON subject.id = s.subject_id\n" +
                            "WHERE s.subject_id IN (:subjects)\n" +
                            "AND s.academy_year_id = :academy_year_id\n" +
                            "AND s.term_id = :term_id\n" +
                            "AND s.section_id = :section_id"
                    ,
                    resultSetMapping = "StudentAssessmentValue"
            )

Это код в моем репозитории

 @Query(nativeQuery = true, name = "getStudentSubjectsAssessment")
  List<StudentAssessmentDTO> getStudentAssessments2(
        @Param("student_id") String student_id,
        @Param("academy_year_id") Integer academy_year_id,
        @Param("section_id") Integer section_id,
        @Param("term_id") Integer term_id,
        @Param("subjects") Integer[] subjects
);

И у меня есть это в моем контроллере

   @GetMapping("/{student_id}/{academy_year_id}/{section_id}/
   term_id}")
    public List<StudentAssessmentDTO> getStudentAssessment2(
        @PathVariable("student_id") String student_id,
        @PathVariable("academy_year_id") Integer academy_year_id,
        @PathVariable("section_id") Integer section_id,
        @PathVariable("term_id") Integer term_id,
        @RequestParam(value = "subjects") Integer[] subjects
   ){
    return assessmentService.getStudentAssessments2(student_id, academy_year_id, section_id, term_id, subjects);
   }

Я также заметил, удаляю ли я эту часть из запроса, ГДЕ s.subject_id IN (: subject), или говорю, что я жестко кодирую значение субъектов, как, например, s.subject_id IN (2,3,4), код выполняется успешно. Но если значение приходит из запроса, я получаю ошибку. Вот как выглядит запрос:

localhost: 8080 /valuation / f3df0bc2-7b4c-49b9-86c9-6e6b01628623 / 3/4/1? Subject = 2,3,4

Ответы [ 2 ]

1 голос
/ 08 октября 2019

У меня недавно была проблема, аналогичная вашей , но я также работал с нативным JPA-запросом на Postgres. Вот что сработало для меня:

// sqlString contains your native query

Query query = entityManager.createNativeQuery(sqlString, StudentAssessmentDTO.class);
query.setParameter("subjects", subjects);
query.setParameter("academy_year_id", new TypedParameterValue(IntegerType.INSTANCE, academy_year_id));
query.setParameter("term_id", new TypedParameterValue(IntegerType.INSTANCE, term_id));
query.setParameter("section_id", new TypedParameterValue(IntegerType.INSTANCE, section_id));
List< StudentAssessmentDTO > = query.getResultList();

Ошибка, которую вы видите, может быть объяснена неспособностью драйвера JDBC Postgres правильно передать необходимую информацию о типе в базу данных. Например, следующая ошибка:

ОШИБКА: оператор не существует: целое число = bytea

произойдет, потому что драйвер передает параметр в Postgres как байтовый массив, но целевой столбец имеет целочисленный тип. Используя вышеупомянутые «подсказки», мы можем заставить драйвер передавать правильную информацию о типе.

0 голосов
/ 09 октября 2019

Возможно, это не лучшее решение, но оно работает для меня, я буду рад, если кто-нибудь еще сможет предложить лучшее решение.

Вот что я сделал:

Я написал метод, который будет принимать массив, полученный из запроса, и генерировать строку такого типа "(a,b,c)", а затем добавить эту строку в строку запроса, и она будет работать

CODE

Thisэто метод построения строки ПРИМЕЧАНИЕ: я могу позволить себе использовать эту функцию, потому что я точно знаю, что элемент этого массива не растет быстро, максимум для моего случая будет 15

 public String generateInSearchParameter(Integer[] inputArr){
    StringBuilder search = new StringBuilder("(");

    IntStream.range(0, inputArr.length).forEach(i -> {
        if (i != inputArr.length - 1) {
            search.append(inputArr[i]).append(',');
        } else {
            search.append(inputArr[i]);
        }
    });

     search.append(")");

     return search.toString();
  }

Вот код контроллера

 @GetMapping("/{student_id}/{academy_year_id}/{section_id}/{term_id}")
    public List<StudentAssessmentDTO> getStudentAssessment2(
            @PathVariable("student_id") String student_id,
            @PathVariable("academy_year_id") Integer academy_year_id,
            @PathVariable("section_id") Integer section_id,
            @PathVariable("term_id") Integer term_id,
            @RequestParam(value = "subjects") Integer[] subjects
    ){
        return assessmentService.getStudentAssessments2(student_id, academy_year_id, section_id, term_id,generateInSearchParameter(subjects));

    }

Вот код в моей службе

public List<StudentAssessmentDTO> getStudentAssessments2(
            String student_id, Integer academy_year_id,
            Integer section_id, Integer term_id, String subjects
    ){

        String sqlString = "SELECT" +
                " subject.subject_title," +
                " j.*" +
                " FROM  assessment s" +
                " JOIN   LATERAL jsonb_array_elements(s.assessment) j(elem) ON (j.elem->>'student_id') = :student_id" +
                " JOIN subject ON subject.id = s.subject_id" +
                " WHERE s.academy_year_id = :academy_year_id" +
                " AND s.section_id = :section_id" +
                " AND s.subject_id IN " + subjects +
                " AND s.term_id = :term_id";

        Query query = entityManager.createNativeQuery(sqlString, "StudentAssessmentValue");
        query.setParameter("academy_year_id", new TypedParameterValue(IntegerType.INSTANCE, academy_year_id));
        query.setParameter("term_id", new TypedParameterValue(IntegerType.INSTANCE, term_id));
        query.setParameter("section_id", new TypedParameterValue(IntegerType.INSTANCE, section_id));
        query.setParameter("student_id", new TypedParameterValue(StringType.INSTANCE, student_id));

        return query.getResultList();

    }

Я буду рад приветствовать лучшее решение, если оно будет предоставлено

...