簡體   English   中英

spring data jpa - 帶有自定義查詢的基於類的投影

[英]spring data jpa - class based projections with custom query

我需要一個用於自定義查詢的 spring 數據存儲庫方法,並希望使用基於類的投影。

看着這個https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

@Entity
public class Person {
  @Id
  private Long id;
  private String firstName;
  private String lastName;
  private int age;
}

@Value // lombok annotation to create constructor, equals and hash-code
public class PersonDTO {
  private String firstName;
  private String lastName;
}

public interface PersonRepository extends Repository<Person, Long> {

List<PersonProjection> findDistinct();

@Query("select distinct firstName, lastName from Person")
List<PersonProjection> findDistinctQuery();

@Query(value = "select distinct first_name, last_name from person", nativeQuery = true)
List<PersonProjection> findDistinctNativeQuery();

}
  • findDistinct 效果很好
  • findDistinctQuery 和 findDistinctNativeQuery 拋出

沒有找到能夠從類型 [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] 轉換為類型 [com.x.PersonDTO] 的轉換器

是否有任何選項可以使其與類(而不是接口)一起使用?

請親自編寫您的方法,如下所示

@Query(value = "select distinct new xxx.xxx.dto.PersonDTO(p.first_name, p.last_name) from person p")
List<PersonProjection> findDistinctNativeQuery();

“xxx.xxx.dto.PersonDTO”這應該指向您的完全限定類名。

供您參考,請查看此https://www.bytestree.com/spring/spring-data-jpa-projections-5-ways-return-custom-object/

我不確定是否有適用於本機查詢的 Spring Data 解決方案,但您可以使用 JPA ConstructorResult

@Entity
@NamedNativeQuery(
        name="Person.findDistinctNativeQuery",
        query="select distinct first_name as firstName, last_name as lastName from person",
        resultSetMapping="PersonMapping"
)
@SqlResultSetMapping(name="PersonMapping",
        classes={
                @ConstructorResult(targetClass=PersonDTO.class, columns={
                        @ColumnResult(name="firstName", type=String.class),
                        @ColumnResult(name="lastName", type=String.class)
                })
        })
public class Person {
    @Id
    private Long id;
    private String firstName;
    private String lastName;
    private int age;
}

@Value // lombok annotation to create constructor, equals and hash-code
public class PersonDTO {
    private String firstName;
    private String lastName;
}

public interface PersonRepository extends Repository<Person, Long> {

    List<PersonProjection> findDistinct();

    @Query("select distinct firstName, lastName from Person")
    List<PersonProjection> findDistinctQuery();

    @Query(name = "Person.findDistinctNativeQuery", nativeQuery = true)
    List<PersonDTO> findDistinctNativeQuery();

}

或者您可以從 findDistinctNativeQuery() 返回 Object[],然后手動創建 PersonDTO。

使用 HQL,您也可以使用基於類的投影,唯一的條件 PersonDTO 必須具有所有參數構造函數,其參數名稱必須與根實體類的屬性匹配:

public interface PersonRepository extends Repository<Person, Long> {

    ...

    List<PersonDTO> findDistinct();

}

如果 PersonDTO 屬性與基本實體屬性不匹配,則可以使用HQL 動態實例化 同樣,這不適用於本機查詢:

public interface PersonRepository extends Repository<Person, Long> {

    ...

    @Query("select new com.x.PersonDTO(firstName, lastName) from Person")
    List<PersonDTO> findDistinct();

}

這也有效:

public interface PersonRepository extends CrudRepository<Person, Long> {

    @Query(nativeQuery = true,
        value = "SELECT DISTINCT fist_name AS firstName, last_name AS lastName FROM person ")
    List<PersonNameOnly> findDistinctNames();

    interface PersonNameOnly {
        String getFirstName;
        String getLastName;
    }
}

這可以通過FluentJPA完成:

default List<PersonDTO> findDistinctQuery() {
    FluentQuery query = FluentJPA.SQL((Person p) -> {
        SELECT(DISTINCT(p.getFirstName(), p.getLastName()));
        FROM(p);
    });
    return query.createQuery(getEntityManager(), PersonDTO.class).getResultList();
}

請注意,您必須使用@Data而不是@Value注釋@Value 有關JPA 存儲庫集成的更多詳細信息。

您需要添加具有與根實體相同的字段名稱的構造函數。 所以你的 DTO 將是,

public class PersonDTO {
  private String firstName;
  private String lastName;
  // constructor , getters setters, equals(…) and hashCode() implementations 
}

您可以使用 Lombok 的@Value注釋來簡化 DTO,

 @Value
 class PersonDTO {
    String firstname, lastname;
 }

在此處查看更多詳細信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM