Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring JPA native query with Projection gives "ConverterNotFoundException"

Tags:

I'm using Spring JPA and I need to have a native query. With that query, I need to get only two fields from the table, so I'm trying to use Projections. It isn't working, this is the error I'm getting:

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] 

I tried to follow precisely the instructions of that page I linked, I tried to make my query non-native (do I actually need it to be native if I use projections, btw?), but I always get that error.
If I use an interface it works, but the results are proxies and I really need them to be "normal results" that I can turn into json.

So, here's my code. The Entity:

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; } 

The class for the 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; } 

The Repository:

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

And the code that tries to get the data:

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

Thanks for the help. I really don't understand what I'm doing wrong.

like image 944
nonzaprej Avatar asked Mar 26 '18 20:03

nonzaprej


People also ask

How do I return DTO from native queries with Spring data JPA?

Spring Data JPA doesn't provide an automatic mapping of class-based DTOs for native queries. The easiest way to use this projection is to define your query as a @NamedNativeQuery and assign an @SqlResultSetMapping that defines a constructor result mapping.

What is Spring JPA projection?

Overview. When using Spring Data JPA to implement the persistence layer, the repository typically returns one or more instances of the root class. However, more often than not, we don't need all the properties of the returned objects. In such cases, we might want to retrieve data as objects of customized types.

How do you map native query results to entities?

You can do this with a @SqlResultSetMapping which specifies the mapping for each entity attribute. As you can see in the code snippet, the @SqlResultSetMapping requires a name and an @EntityResult annotation which defines the mapping to the entity.


1 Answers

with spring data you can cut the middle-man and simply define

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

and use a native query like;

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

check out https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

like image 200
shahaf Avatar answered Sep 19 '22 18:09

shahaf