0

I am trying to obtain a non-entity object, using a native query, which I'd like to use as a model for a view on one of the pages in my application. I am following this explanation which doesn't go in much detail, it is more like a cheat-sheet for someone who is already familiar with the topic and only needs a reminder. There are similar questions here and here from ages ago and since I can’t figure out where exactly the provided code blocks should go I tought I might ask a fresh question. What ever I try I get this exception:

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

Here is my model class:

public class ProductForHomeView {

    private int id;
    private String title;
    private EProductType productType;
    private double price;
    private int quantity;

    public ProductForHomeView(int id, String title, EProductType productType, double price, int quantity) {
        this.id = id;
        this.title = title;
        this.productType = productType;
        this.price = price;
        this.quantity = quantity;
    }

The Repository interface:

public interface IProductsRepository extends CrudRepository<Products, Integer> {
    @Query(value = "SELECT products.id, products.title, products.the_type AS productType, stock.price, stock.quantity FROM products LEFT JOIN stock on products.id=stock.product_id", nativeQuery = true)
    List<ProductForHomeView> getProductsInfoForTheHomePage();   
}

And one of the entity classes where I try to map the non-entity class:

@Entity
@Table(name = "stock")
@SqlResultSetMapping(
        name="ProductForHomeViewMapping",
        classes={
        @ConstructorResult(
        targetClass=qualified.name.ProductForHomeView.class,
        columns={
        @ColumnResult(name="id", type=Integer.class),
        @ColumnResult(name="title", type=String.class),
        @ColumnResult(name="productType", type=EProductType.class),
        @ColumnResult(name="price", type=Long.class),
        @ColumnResult(name="quantity", type=String.class)
        })})
public class Stock {
// mapped fields, constructors, geters and setters...
}

I appreciate any input!

Ogorodin
  • 15
  • 6

2 Answers2

0

I used @SqlResultSetMapping with @NamedNativeQuery

Change your Curd repository method with following

public interface IProductsRepository extends CrudRepository<Products, Integer> {
    @NamedNativeQuery(value = "SELECT products.id, products.title, products.the_type AS productType, stock.price, stock.quantity FROM products LEFT JOIN stock on products.id=stock.product_id", resultSetMapping = "ProductForHomeViewMapping")
    List<ProductForHomeView> getProductsInfoForTheHomePage();   
}

More info is available here

Devratna
  • 938
  • 1
  • 7
  • 26
  • Are you sure we can use the annotation `@NamedNativeQuery` on a method declaration like this? – Andrianekena Moise Mar 27 '19 at 09:21
  • I second the question since I didn't find a source where annotating a method declaration like this is possible. The link provided is very informative but isn't offering an answer on the question 'How to map native queries to NON-ENTITY objects?' – Ogorodin Mar 28 '19 at 08:05
0

You may declare your view as an interface and then Spring Data will handle it they way you want.

Here is the example:

https://github.com/roberthunt/spring-data-native-query-projection/blob/master/src/main/java/uk/co/rbrt/PersonSummary.java

https://github.com/roberthunt/spring-data-native-query-projection/blob/master/src/main/java/uk/co/rbrt/PersonRepository.java