Как запустить Hibernate NativeQuery типобезопасным способом вместо возврата объекта [] - PullRequest
0 голосов
/ 06 сентября 2018

Я переношу приложение из Hibernate 4.x в Hibernate 5.3.6.У приложения есть такие запросы:

SQLQuery query = getSession().createSQLQuery("SELECT a.a, a.b, a.c FROM aTable");

Поскольку метод createSQLQuery устарел, я сначала заменил вызов метода альтернативой, предложенной в Hibernate Javadoc, а именно с помощью createNativeQuery:

NativeQuery query = getSession().createNativeQuery("SELECT a.a, a.b, a.c FROM aTable");

Проблема заключается в том, что он выдает предупреждение компилятора «NativeQuery - это необработанный тип. Ссылки на универсальный тип NativeQuery должны быть параметризованы».Кроме того, конечно, я хотел бы получить выгоду от типизированных запросов, теперь, когда они доступны.Поэтому я изменил запрос на

NativeQuery<Object[]> query = getSession().createNativeQuery("SELECT a.a, a.b, a.c FROM aTable", Object[].class);

Теперь проблема состоит в том, что выполнение запроса с помощью

List<Object[]> retList = query.list();

приводит к ошибке

javax.persistence.PersistenceException: org.hibernate.MappingException: Неизвестная сущность: [Ljava.lang.Object;

Исследование проблемы , кажется, указывает , что невозможно использовать не отображенные сущности, когдаиспользование типизированных собственных запросов (что кажется серьезным и ненужным ограничением, но я отступлю здесь).

Вопрос: есть ли способ до выполнить собственный SQL-запрос, возвращающий массив объектов с использованием Hibernate без , выдающий предупреждения компилятора пока достижение безопасности типа?Если нет, есть ли разумная альтернатива?

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Как я объяснил в этой статье , есть гораздо лучшие альтернативы для таких проекций, чем по умолчанию Object[].

  1. Вы можете использовать набор результатов JPA javax.persistence.Tuple, который, поскольку Hibernate ORM 5.2.11 работает для собственного SQL:

    List<Tuple> postDTOs = entityManager
    .createNativeQuery(
        "SELECT " +
        "       p.id AS id, " +
        "       p.title AS title " +
        "FROM Post p " +
        "WHERE p.created_on > :fromTimestamp", Tuple.class)
    .setParameter( "fromTimestamp", Timestamp.from(
        LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
            .toInstant( ZoneOffset.UTC ) ))
    .getResultList();
    
  2. Вы можете использовать специфичный для Hibernate ResultTransformer, который позволяет создавать очень сложные структуры DTO (например, графики):

    List postDTOs = entityManager
    .createNativeQuery(
        "select " +
        "       p.id as \"id\", " +
        "       p.title as \"title\" " +
        "from Post p " +
        "where p.created_on > :fromTimestamp")
    .setParameter( "fromTimestamp", Timestamp.from(
        LocalDateTime.of( 2016, 1, 1, 0, 0, 0 ).toInstant( ZoneOffset.UTC ) ))
    .unwrap( org.hibernate.query.NativeQuery.class )
    .setResultTransformer( Transformers.aliasToBean( PostDTO.class ) )
    .getResultList();
    
  3. Вы также можете использовать именованный собственный запрос:

    List<PostDTO> postDTOs = entityManager
    .createNamedQuery("PostDTO")
    .setParameter( "fromTimestamp", Timestamp.from(
        LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
            .toInstant( ZoneOffset.UTC ) ))
    .getResultList();
    

    где PostDTO запрос - это именованный собственный SQL-запрос, который выглядит следующим образом:

    @NamedNativeQuery(
        name = "PostDTO",
        query =
            "SELECT " +
            "       p.id AS id, " +
            "       p.title AS title " +
            "FROM Post p " +
            "WHERE p.created_on > :fromTimestamp",
        resultSetMapping = "PostDTO"
    )
    @SqlResultSetMapping(
        name = "PostDTO",
        classes = @ConstructorResult(
            targetClass = PostDTO.class,
            columns = {
                @ColumnResult(name = "id"),
                @ColumnResult(name = "title")
            }
        )
    )
    

Круто, верно?

0 голосов
/ 06 сентября 2018

Просто создайте его с помощью звонка

createNativeQuery("SELECT a.a, a.b, a.c FROM aTable");

и по умолчанию возвращается строка Object[].

Предупреждение не имеет значения для вашего случая, поэтому просто подавьте его.

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