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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With