Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA Data Repositories with SqlResultSetMapping and native queries

I was stuck with the following situation:

My entities are related to each other, but in such a way that i could not use JPQL. I was forced to use native SQL. Now I want to map these results to a ValueObject. To be clear, I don't want to get a list of Object array (List<Object[]>). I have 6 entities from which I need only some columns. Can anybody give me an example on how to implement such a mapping from a native query?

Tutorial that I went through.

My code:

@SqlResultSetMapping(
    name = "findAllDataMapping",
    classes = @ConstructorResult(
            targetClass = MyVO.class,
            columns = {
                    @ColumnResult(name = "userFirstName"),
                    @ColumnResult(name = "userLastName"),
                    @ColumnResult(name = "id"),
                    @ColumnResult(name = "packageName")
            }
    )
)

@NamedNativeQuery(name = "findAllDataMapping",
    query = "SELECT " +
            "    u.first_name as userFirstName, " +
            "    u.last_name as userLastName, " +
            "    i.id as id, " +
            "    s.title as packageName, " +
            "FROM " +
            "    invoice as i " +
            "JOIN user as u on i.user_id=u.id " +
            "LEFT JOIN subscription_package as s on i.subscription_package_id=s.id " +
            "where  u.param1=:param1 and i.param2=:param2" +
)

public class MyVO {
    private String userFirstName;
    private String userLastName;
    private Long id;
    private String packageName;

    public MyVO (String userFName, String userLName,
            Long id, String packageName) {
        this.userFirstName = userFName;
        this.userLastName = userLName;
        this.id = id;
        this.packageName = packageName;
    }

    // getters & setters
}

In my jpa-repository module:

public interface MyRepository extends JpaRepository<MyEntity, Long> {
    List<MyVO> findAllOfMyVO(@Param("param1") String param1, @Param("param2") String param2);
}

The point is that I don't know where to put these annotations so I can use this kind of mapping. In a native query I can't use new rs.rado.leo.mypackage.MyVO(...). I got following error:

Caused by:

org.springframework.data.mapping.PropertyReferenceException: No property findAllOfMyVO found for type MyEntity!

I suppose that my question is clear. If not, let me know so I can edit my question.

Thanks in advance!

like image 742
LeoRado Avatar asked Sep 12 '17 08:09

LeoRado


People also ask

How do you return DTOs 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 the use of native query in JPA?

Native query refers to actual sql queries (referring to actual database objects). These queries are the sql statements which can be directly executed in database using a database client. 2. Named query is the way you define your query by giving it a name.

Which are the JPA database repository?

JpaRepository is a JPA (Java Persistence API) specific extension of Repository. It contains the full API of CrudRepository and PagingAndSortingRepository. So it contains API for basic CRUD operations and also API for pagination and sorting.


1 Answers

Add the missing resultClass

@NamedNativeQuery(name = "findAllDataMapping", resultClass = Entity.class, query="sql")

Or

@NamedNativeQuery(name = "findAllDataMapping", resultClass = MyVO.class, resultSetMapping ="findAllDataMapping" query = "sql")

and lastly call the query in your repository

@Query(nativeQuery = true, name = "findAllDataMapping")
List<MyVO> findAllOfMyVO(@Param("param1") String param1, @Param("param2") String param2);
like image 105
Michelan Arendse Avatar answered Oct 21 '22 16:10

Michelan Arendse