Spring Data JPA asigna el resultado de la consulta nativa al POJO sin entidad

Tengo un método de repository de Spring Data con una consulta nativa

@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true) GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId); 

y me gustaría asignar el resultado a los GroupDetails POJO que no sean de la Entidad.

¿Es posible y, en caso afirmativo, podría dar un ejemplo?

Asumiendo GroupDetails como en la respuesta de orid ¿has probado JPA 2.1 @ConstructorResult ?

 @SqlResultSetMapping( name="groupDetailsMapping", classes={ @ConstructorResult( targetClass=GroupDetails.class, columns={ @ColumnResult(name="GROUP_ID"), @ColumnResult(name="USER_ID") } ) } ) @NamedNativeQuery(name="getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping") 

y use following en la interfaz del repository:

 GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId); 

De acuerdo con la documentación de Spring Data JPA, Spring intentará primero buscar una consulta con nombre que coincida con el nombre de su método, de modo que al usar @NamedNativeQuery , @SqlResultSetMapping y @ConstructorResult debería poder lograr ese comportamiento.

Creo que la forma más fácil de hacerlo es usar la llamada proyección. Puede mapear resultados de consultas a interfaces. Usar SqlResultSetMapping es SqlResultSetMapping y hace que tu código sea feo :).

Un ejemplo desde el código fuente JPA de datos de spring:

 public interface UserRepository extends JpaRepository { @Query(value = "SELECT firstname, lastname FROM SD_User WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id); public static interface NameOnly { String getFirstname(); String getLastname(); } } 

También puede usar este método para obtener una lista de proyecciones.

Consulte esta entrada de documentos JPA de datos de spring para obtener más información sobre las proyecciones.

Nota: recuerde tener su entidad de User definida como normal: los campos de la interfaz proyectada deben coincidir con los campos de esta entidad. De lo contrario, el mapeo de campo podría estar roto ( getFirstname() podría devolver el valor del apellido, etcétera).

Si GroupDetails es algo así como:

 public class GroupDetails { int groupId; int userId; public GroupDetails(int groupId , int userId) { this.groupId = groupId; this.userId = userId; } // getters setters, etc. } 

Lo siguiente debería funcionar:

@Query(value = "SELECT new GroupDetails(gm.group_id, gm.user_id) FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId")

Puedes hacer algo como

 @NamedQuery(name="IssueDescriptor.findByIssueDescriptorId" , query=" select new com.test.live.dto.IssuesDto (idc.id, dep.department, iss.issueName, cat.issueCategory, idc.issueDescriptor, idc.description) from Department dep inner join dep.issues iss inner join iss.category cat inner join cat.issueDescriptor idc where idc.id in(?1)") 

Y debe haber un Constructor como

 public IssuesDto(long id, String department, String issueName, String issueCategory, String issueDescriptor, String description) { super(); this.id = id; this.department = department; this.issueName = issueName; this.issueCategory = issueCategory; this.issueDescriptor = issueDescriptor; this.description = description; } 

En mi computadora, obtengo este código. Es un poco diferente de la respuesta de Daimon.

 @SqlResultSetMapping( name="groupDetailsMapping", classes={ @ConstructorResult( targetClass=GroupDetails.class, columns={ @ColumnResult(name="GROUP_ID",type=Integer.class), @ColumnResult(name="USER_ID",type=Integer.class) } ) } ) @NamedNativeQuery(name="User.getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping")