Поиск в спящем режиме: получение параметризованного результата из запроса без непроверенных предупреждений - PullRequest
0 голосов
/ 01 ноября 2018

Можно ли получить параметризованный результат из запроса без непроверенных предупреждений в Hibernate Search?

В Hibernate ORM (5.3.7.Final) можно написать следующий код без каких-либо непроверенных предупреждений:

List<Entity> result = session.createQuery("from Entity", Entity.class).list();

Но в Hibernate Search (5.10.4.Final) в настоящее время я не могу получить параметризованный результат, хотя Entity.class указывается два раза при создании и выполнении запроса:

QueryBuilder queryBuilder = fullTextSession
                .getSearchFactory()
                .buildQueryBuilder()
                .forEntity(Entity.class)
                .get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
                .keyword()
                .onField("field")
                .matching("value")
                .createQuery();
Query query = fullTextSession.createFullTextQuery(luceneQuery, Entity.class);
List result = query.list();

Конечно, я могу написать что-то вроде:

Query<Entity> query = fullTextSession.createFullTextQuery(luceneQuery, Entity.class);
List<Entity> result = query.list();

Но это непроверенное задание.

Или я могу написать

List<Entity> parametrisedResult = (List<Entity>) result;

Но здесь у меня есть непроверенный актерский состав.

Поскольку Hibernate ORM имеет такую ​​возможность, я предполагаю, что в Hibernate Search также можно писать код без непроверенных предупреждений.

Заранее спасибо.

1 Ответ

0 голосов
/ 02 ноября 2018

Нет, в настоящее время невозможно создать безопасный тип FullTextQuery (причины приведены ниже). Рекомендуемый подход, который будет хорошо работать с Search 5.10, а также со старыми (до 5.7) версиями:

QueryBuilder queryBuilder = fullTextSession
                .getSearchFactory()
                .buildQueryBuilder()
                .forEntity(Entity.class)
                .get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
                .keyword()
                .onField("field")
                .matching("value")
                .createQuery();

FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery, Entity.class);
List<Entity> result = (List<Entity>) query.list();

Почему?

Возможность создания безопасного типа запроса является довольно новой по стандартам ORM: она шла с JPA 2.1 (ORM 5.2). До этого метод list() использовался для возврата необработанного List (без параметров универсального типа) в ORM, как и в запросах Hibernate Search.

Поиск Hibernate не изменился, чтобы следовать ORM, хотя: FullTextQuery расширяет org.hibernate.query.Query как необработанный тип, без каких-либо параметров. Причина в том, что в объекте FullTextQuery имеются мутаторы, которые позволяют изменять возвращаемые объекты и, следовательно, возвращаемый тип (в частности, метод setProjection). Так что, хотя мы могли бы вернуть FullTextQuery<Entity> при создании запроса, это могло бы ввести в заблуждение, поскольку в некоторых случаях вы могли бы получить FullTextQuery<Entity>, который фактически возвращает результаты типа List<Object[]> .

Мы исследовали несколько вариантов решения этой ситуации, но не смогли найти решение, которое одновременно гарантировало бы безопасность типов и позволяло бы сохранить обратную совместимость. Итак, мы отказались от этого для Hibernate Search 5.

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

В следующей версии Hibernate Search, версии 6, это будет решено, однако. Новые API построения запросов требуют указания того, будет ли запрос возвращать управляемые объекты или проекции индекса до того, как создаст запрос. Hibernate Search 6 еще не стабилен и не готов к работе, но если вам интересно, вы можете найти пример здесь (вызов asEntity сообщает Search, каким должен быть тип возвращаемого значения).

...