Класс POJO для сопоставления собственных запросов JPA со значением JSONB в PostgreSQL

Я пытался извлечь объединенные значения из нескольких таблиц в пользовательский POJO, используя собственный запрос. Одним из значений, которые я хочу получить, является поле JSONB. Несмотря на то, что я могу получить сущность с этим полем, я получаю исключение 'org.hibernate.MappingException: No Dialect для JDBC type: 1111' исключение, когда я форсирую его в пользовательский POJO. Вот что я использовал:

CREATE TABLE book (
  id BIGSERIAL NOT NULL PRIMARY KEY,
  data JSONB NOT NULL
);
CREATE TABLE price (
  book_id BIGSERIAL NOT NULL PRIMARY KEY,
  price NUMERIC(19,2) NOT NULL
);
INSERT INTO book (id, data) VALUES (0, '{"value": "someValue"}');
INSERT INTO price (book_id, price) VALUES (0, 10.00);

Использование POJO:

@Entity
@TypeDef(defaultForType = MyJson.class, name = "MyJsonType", typeClass = MyJsonType.class)
@Data
@SqlResultSetMapping(name = "CustomMapping",
        classes = {
                @ConstructorResult(targetClass = CustomPOJO.class,
                        columns = {@ColumnResult(name = "id"),
                                @ColumnResult(name = "data"),
                                @ColumnResult(name = "price")})
        })
public class Book {

    @Id
    @GeneratedValue
    Long id;

    @Column(nullable = false, columnDefinition = "JSONB")
    MyJson data;
}

Это класс MyJson:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyJson implements Serializable {

    private String value;
}

А также

@Entity
@Data
@NoArgsConstructor
public class Price {

    @Id
    private Long id;
    private BigDecimal price;
}

И мой обычай POJO

@AllArgsConstructor
@Data
public class CustomPOJO {

    private Long id;
    private MyJson data;
    private BigDecimal price;
}

Пользовательское отображение диалекта @TypeDef реализовано следующим образом. @SqlResultSetMapping я получил отсюда. Теперь я пытаюсь сделать запрос, используя мое собственное отображение:

String query = "SELECT id, data, price\n" +
               "FROM book, price\n" +
               "WHERE book.id = price.book_id;";
Query nativeQuery = em.createNativeQuery(query, "CustomMapping");
@SuppressWarnings("unchecked")
List<CustomPOJO> customPOJOS = nativeQuery.getResultList();

Я понимаю, что hibernate не распознает определение типа, когда я использую свою пользовательскую аннотацию SqlResultSetMapping. Как я могу это исправить? Обратите внимание, что я не могу использовать TypedQueries, так как мои реальные запросы являются более сложными, чем я могу обработать с помощью синтаксиса запроса JPA. При необходимости я могу загрузить пример проекта на github.

1 ответ

Решение

Мне удалось это исправить. Как выяснилось, вам нужно указать каждому столбцу в SqlResultSetMapping, какой тип он должен представлять. Для поля Jsonb класса поля MyJson вам нужно использовать пользовательский класс UserType 'MyJsonType' ( Реализация на этом сайте). Это выглядит так:

@SqlResultSetMapping(name = "CustomMapping",
        classes = {
                @ConstructorResult(targetClass = CustomPOJO.class,
                        columns = {@ColumnResult(name = "id", type = Long.class),
                                @ColumnResult(name = "data", type = MyJsonType.class),
                                @ColumnResult(name = "price", type = BigDecimal.class)})
        })

Очевидно, что вам нужен соответствующий конструктор для пользовательского класса pojo, в моем примере об этом позаботилась аннотация @AllArgsConstructor.

Другие вопросы по тегам