Yoann Rodière (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
) *created* an issue
Hibernate Search (
https://hibernate.atlassian.net/browse/HSEARCH?atlOrigin=eyJpIjoiNTYzYTJl...
) / New Feature (
https://hibernate.atlassian.net/browse/HSEARCH-3927?atlOrigin=eyJpIjoiNTY...
) HSEARCH-3927 (
https://hibernate.atlassian.net/browse/HSEARCH-3927?atlOrigin=eyJpIjoiNTY...
) Projection to a DTO/JavaBean/etc. (
https://hibernate.atlassian.net/browse/HSEARCH-3927?atlOrigin=eyJpIjoiNTY...
)
Issue Type: New Feature Assignee: Unassigned Components: engine Created: 26/May/2020 04:35
AM Fix Versions: 6.0.0-Bonus-backlog Priority: Major Reporter: Yoann Rodière (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
)
Currently the only way to build an object for each hit is to define a composite projection
by hand:
public class TitleAndGenre {
public final String title;
public final Genre genre;
public TitleAndGenre( String title, Genre genre) {
...
}
}
List<TitleAndGenre> hits = searchSession.search( Book.class )
.select( f -> f.composite(
TitleAndGenre:: new ,
f.field( "title" , String.class ),
f.field( "genre" , Genre.class )
) )
.where( f -> f.matchAll() )
.fetchHits( 20 );
That's fine when there are just two or three fields involved, but it can quickly
become very verbose, especially if nested objects must be created.
We should introduce a way to automate the process. The user would simply define a class,
and ask that we project to that class.
// Project on fields "title" and "genre"
.select( f -> f.object( TitleAndGenre.class ) )
// Maybe also add a shorthand
.select( TitleAndGenre.class )
// Project on fields "someAssociation.title" and
"someAssociation.genre"
.select( f -> f.object( "someAssociation" , TitleAndGenre.class ) )
We would need to:
* Discover the constructors of the given type
* Enforce that there is only one constructor
* Discover the constructor parameters (name and type)
* Create one field projection per constructor parameter
* Create a composite projection to aggregate the field projections
* Return the composite projection
Several things will have to be considered:
* Can we assume that the name of constructor parameters is always available? IIRC, a
specific flag is needed at compilation time, but maybe it's no longer the case in
recent versions of Java. See Hibernate Validator.
* Do we want to pass the field values through the constructor or through setters? Maybe
offer the choice?
* We will probably need a way to handle "nested" projection classes, i.e. have a
parameter of the projection class constructor whose type is also a projection class. In
this case the parameter name would be the name of an object field.
Follow-up ideas:
* Maybe we'll need a way to pre-declare such "projection classes", so that
they can be validated on bootstrap, and more importantly so that they are discovered when
we can use reflection (in native mode, we can't use reflection after bootstrap).
* What about records? (Java 14+, I believe)
* This feature would be very useful to introduce a standalone Elasticsearch mapper, where
Elasticsearch is the primary source of truth and thus entities have to be created from
Elasticsearch documents.
(
https://hibernate.atlassian.net/browse/HSEARCH-3927#add-comment?atlOrigin...
) Add Comment (
https://hibernate.atlassian.net/browse/HSEARCH-3927#add-comment?atlOrigin...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100127- sha1:dccb6b5 )