복붙노트

[SPRING] 스프링 데이터 JPA는 네이티브 쿼리 결과를 비 엔티티 POJO에 매핑합니다.

SPRING

스프링 데이터 JPA는 네이티브 쿼리 결과를 비 엔티티 POJO에 매핑합니다.

네이티브 쿼리를 사용하여 Spring 데이터 저장소 메서드가 있습니다.

@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true)
    GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);

결과를 비 엔티티 POJO GroupDetails에 매핑하고 싶습니다.

가능합니까? 그렇다면 예를 들어 주시겠습니까?

해결법

  1. ==============================

    1.GroupDetails를 orid의 대답과 같이 가정하면 JPA 2.1 @ConstructorResult를 시도한 적이 있습니까?

    GroupDetails를 orid의 대답과 같이 가정하면 JPA 2.1 @ConstructorResult를 시도한 적이 있습니까?

    @SqlResultSetMapping(
        name="groupDetailsMapping",
        classes={
            @ConstructorResult(
                targetClass=GroupDetails.class,
                columns={
                    @ColumnResult(name="GROUP_ID"),
                    @ColumnResult(name="USER_ID")
                }
            )
        }
    )
    
    @NamedNativeQuery(name="getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping")
    

    저장소 인터페이스에서 다음을 사용하십시오.

    GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);
    

    Spring Data JPA 문서에 따르면 Spring은 메소드 이름과 일치하는 명명 된 쿼리를 찾기 위해 먼저 시도합니다. @NamedNativeQuery, @SqlResultSetMapping 및 @ConstructorResult를 사용하면 해당 동작을 수행 할 수 있습니다.

  2. ==============================

    2.가장 쉬운 방법은 프로젝션을 사용하는 것입니다. 쿼리 결과를 인터페이스에 매핑 할 수 있습니다. SqlResultSetMapping을 사용하면 코드가 불완전 해지고 코드가 엉망이됩니다. :)

    가장 쉬운 방법은 프로젝션을 사용하는 것입니다. 쿼리 결과를 인터페이스에 매핑 할 수 있습니다. SqlResultSetMapping을 사용하면 코드가 불완전 해지고 코드가 엉망이됩니다. :)

    JPA 소스 코드의 스프링 데이터 예제

    public interface UserRepository extends JpaRepository<User, Integer> {
    
       @Query(value = "SELECT firstname, lastname FROM SD_User WHERE id = ?1", nativeQuery = true)
       NameOnly findByNativeQuery(Integer id);
    
       public static interface NameOnly {
    
         String getFirstname();
    
         String getLastname();
    
      }
    }
    

    이 방법을 사용하여 투영 목록을 얻을 수도 있습니다.

    투영에 대한 자세한 정보는이 봄 데이터 JPA 문서 항목을 확인하십시오.

    참고 1 :

    User 엔티티를 정상적으로 정의해야합니다. 투영 된 인터페이스의 필드는이 엔티티의 필드와 일치해야합니다. 그렇지 않으면 필드 매핑이 깨질 수 있습니다 (getFirstname ()은 성 등의 값을 반환 할 수 있음).

    노트 2:

    SELECT table.column ... notation을 사용하면 항상 엔티티의 이름과 일치하는 별명을 정의하십시오. 예를 들어이 코드는 제대로 작동하지 않을 것입니다 (프로젝션은 각 getter에 대해 null을 반환합니다).

    @Query(value = "SELECT user.firstname, user.lastname FROM SD_User user WHERE id = ?1", nativeQuery = true)
    NameOnly findByNativeQuery(Integer id);
    

    그러나 이것은 잘 작동합니다.

    @Query(value = "SELECT user.firstname AS firstname, user.lastname AS lastname FROM SD_User user WHERE id = ?1", nativeQuery = true)
    NameOnly findByNativeQuery(Integer id);
    
  3. ==============================

    3.GroupDetails가 다음과 같은 경우 :

    GroupDetails가 다음과 같은 경우 :

    public class GroupDetails {
    
        int groupId;
        int userId;
    
        public GroupDetails(int groupId , int userId) {
            this.groupId = groupId;
            this.userId = userId;
        }
    
        // getters setters, etc.
    }
    

    다음은 작동합니다.

    @Query (값 = "새 그룹 상세 선택 (gm.group_id, gm.user_id) 그룹 g LEFT JOIN group_members gm ON g.group_id = gm.group_id 및 gm.user_id = : userId WHERE g.group_id = : groupId")

  4. ==============================

    4.너는 뭔가를 할 수있다.

    너는 뭔가를 할 수있다.

    @NamedQuery(name="IssueDescriptor.findByIssueDescriptorId" ,
    
        query=" select new com.test.live.dto.IssuesDto (idc.id, dep.department, iss.issueName, 
                   cat.issueCategory, idc.issueDescriptor, idc.description) 
                from Department dep 
                inner join dep.issues iss 
                inner join iss.category cat 
                inner join cat.issueDescriptor idc 
                where idc.id in(?1)")
    

    그리고 생성자가 있어야합니다.

    public IssuesDto(long id, String department, String issueName, String issueCategory, String issueDescriptor,
                String description) {
            super();
            this.id = id;
            this.department = department;
            this.issueName = issueName;
            this.issueCategory = issueCategory;
            this.issueDescriptor = issueDescriptor;
            this.description = description;
        }
    
  5. ==============================

    5.내 컴퓨터에서는이 코드가 작동합니다. 다이몬의 대답과는 조금 다릅니다.

    내 컴퓨터에서는이 코드가 작동합니다. 다이몬의 대답과는 조금 다릅니다.

    @SqlResultSetMapping (     name = "groupDetailsMapping",     클래스 = {         @ConstructorResult (             targetClass = GroupDetails.class,             columns = {                 @ColumnResult (name = "GROUP_ID", type = Integer.class),                 @ColumnResult (name = "USER_ID", type = Integer.class)             }         )     } ) @NamedNativeQuery (name = "User.getGroupDetails", query = "SELECT g. *, gm. * FROM 그룹 g LEFT JOIN group_members gm ON g.group_id = gm.group_id 및 gm.user_id = : userId WHERE g.group_id = : groupId ", resultSetMapping ="groupDetailsMapping ")

  6. from https://stackoverflow.com/questions/29082749/spring-data-jpa-map-the-native-query-result-to-non-entity-pojo by cc-by-sa and MIT license