简体   繁体   中英

Hibernate Search: Get parametrised result from query without unchecked warnings

Is it possible to get parametrised result from query without unchecked warnings in Hibernate Search?

In Hibernate ORM (5.3.7.Final) it is possible to write the following code without any unchecked warnings:

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

But in Hibernate Search (5.10.4.Final) I currently can't get parametrised result, even though Entity.class is specified two times during creating and executing a query:

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();

Of course I can write something like:

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

But that's an unchecked assignment.

Or I can write

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

But here I have an unchecked cast.

Since Hibernate ORM has such a possibility, I assume that in Hibernate Search it is also possible to write code without unchecked warnings.

Thanks in advance.

No, it's not currently possible to instantiate a type-safe FullTextQuery (reasons below). The recommended approach is this one, which will work fine with Search 5.10 as well as older (pre-5.7) versions:

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();

Why?

The ability to create a type-safe query is fairly new by ORM standards: it came with JPA 2.1 (ORM 5.2). Before that, the list() method used to return a raw List (without generic type parameters) in ORM, and so did it in Hibernate Search queries.

Hibernate Search did not change to follow ORM, though: FullTextQuery extends org.hibernate.query.Query as a raw type, without any parameter. The reason is, there are mutators on the FullTextQuery object that allow to change the returned objects, and thus the returned type (in particular, the setProjection method). So, even though we could return a FullTextQuery<Entity> when you build a query, that would be misleading, because in some cases you could end up with a FullTextQuery<Entity> that actually returns results of type List<Object[]> .

We explored a few options to resolve this situation, but couldn't find a solution that would both guarantee type-safety and allow to preserve backward compatibility. So we've given up on this for Hibernate Search 5.

In case you're wondering, ORM does not have the same problem, because you specify the exact type you want your query to return when you create your query, and cannot change it afterwards.

In the next major of Hibernate Search, the version 6, this will be solved, however. The new query building APIs require to specify whether the query will return managed entities or an index projections before you create the query. Hibernate Search 6 is not stable yet and is not ready for production, but if you're curious you can find an example here (the asEntity call tells Search what the return type should be).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM