web-dev-qa-db-fra.com

La requête native Spring JPA avec Projection donne "ConverterNotFoundException"

J'utilise Spring JPA et j'ai besoin d'une requête native. Avec cette requête, je n'ai besoin que de deux champs de la table. J'essaie donc d'utiliser Projections . Cela ne fonctionne pas, c'est l'erreur que j'obtiens: 

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.IdsOnly]

J'ai essayé de suivre précisément les instructions de la page que j'ai liée, j'ai essayé de rendre ma requête non native (ai-je réellement besoin qu'elle soit native si j'utilise des projections, d'ailleurs?), Mais je reçois toujours cette erreur.
Si j'utilise une interface, cela fonctionne, mais les résultats sont des proxies et j'ai vraiment besoin qu'ils soient des "résultats normaux" que je peux transformer en json. 

Alors, voici mon code. L'entité: 

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@Entity
@Table(name = "TestTable")
public class TestTable {

    @Id
    @Basic(optional = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "Id")
    private Integer id;
    @Column(name = "OtherId")
    private String otherId;
    @Column(name = "CreationDate")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;
    @Column(name = "Type")
    private Integer type;
}

Le cours pour la projection: 

import lombok.Value;

@Value // This annotation fills in the "hashCode" and "equals" methods, plus the all-arguments constructor
public class IdsOnly {

    private final Integer id;
    private final String otherId;
}

Le référentiel: 

public interface TestTableRepository extends JpaRepository<TestTable, Integer> {

    @Query(value = "select Id, OtherId from TestTable where CreationDate > ?1 and Type in (?2)", nativeQuery = true)
    public Collection<IdsOnly> findEntriesAfterDate(Date creationDate, List<Integer> types);
}

Et le code qui tente d’obtenir les données: 

@Autowired
TestTableRepository ttRepo;
...
    Date theDate = ...
    List<Integer> theListOfTypes = ...
    ...
    Collection<IdsOnly> results = ttRepo.findEntriesAfterDate(theDate, theListOfTypes);  

Merci pour l'aide. Je ne comprends vraiment pas ce que je fais mal.

4
nonzaprej

La requête doit utiliser une expression du constructeur :

@Query("select new com.example.IdsOnly(t.id, t.otherId) from TestTable t where t.creationDate > ?1 and t.type in (?2)")

Et je ne connais pas Lombok, mais assurez-vous qu’il existe un constructeur qui prend les deux identifiants comme paramètres.

7
Robert Niestroj

JPA 2.1 introduit une fonctionnalité ConstructorResult intéressante si vous souhaitez la conserver native

3
Montassar El Béhi

avec les données de printemps, vous pouvez couper l'homme du milieu et simplement utiliser

public interface IdsOnly {
  Integer getId();
  String getOtherId();
}

et utilisez une requête native telle que;

@Query(value = "Id, OtherId from TestTable where CreationDate > ?1 and Type in (?2)", nativeQuery = true)
    public Collection<IdsOnly> findEntriesAfterDate(Date creationDate, List<Integer> types);

vérifier https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

2
shahaf