如何使用 Spring Data 从 Spring Boot 中的实体中选择几个字段?

Bou*_*Dev 5 java spring spring-mvc spring-data-jpa spring-boot

我有一个用例,我想显示实体的内容但隐藏某些字段。我的实体如下 -

实体

public class StudentDetail {

@Id
private Long ID;
private String firstName;
private String middleName;
private String lastName;

@JsonFormat(pattern="dd-MMM-yyyy", timezone="IST")
@Temporal(TemporalType.DATE)
private Date dateOfBirth;
}
Run Code Online (Sandbox Code Playgroud)

它还有许多其他属性,我在这里没有展示。

存储库-

@Repository
public interface StudentDetailsRepository extends JpaRepository<StudentDetail, Integer> {
@Query("select d from StudentDetail d where month(d.dateOfBirth) = ?1 ")
    List<StudentDetail> getStudentListBasedOnDateOfBirth(int month);

}
Run Code Online (Sandbox Code Playgroud)

服务等级-

public List<StudentDetail> getStudentBirthdayDetails(int month) {
        List<StudentDetail> StudentDetail = StudentDetailsRepository.getStudentListBasedOnDateOfBirth(month);
        return StudentDetail;
    }
Run Code Online (Sandbox Code Playgroud)

还有一个控制器类,它通过month参数调用 Service 类来过滤数据集。

我想要做的是修改 Repository 类中的查询并仅包含firstname,middleNamelastName属性。Repository 类应该隐藏该dateOfBirth字段。我意识到以下查询将返回过滤后的项目 -

select d.firstName, d.middleName, d.lastName from StudentDetail d where month(d.dateOfBirth) = ?1 
Run Code Online (Sandbox Code Playgroud)

但是,该类的返回类型Repository是实体类型 StudentDetail 。仅从中选择少数字段将导致错误。所以,我想知道我应该在repo/servicecontroller类中进行哪些更改(假设只有类的返回类型会改变)?

Lpp*_*Edd 8

这称为投影,Spring 为您提供了两种实现它的方法。
请记住,这存在于 JPA 术语中,而不仅仅存在于 Spring 中。

以你Repository为起点

@Repository
public interface StudentDetailsRepository extends JpaRepository<StudentDetail, Integer> {
   ...
}
Run Code Online (Sandbox Code Playgroud)

我们可以用

  1. interface基于投影
    只需创建一个代表您想要的结果的界面

public interface StudentDetailProjection {
   String getFirstName();
   String getMiddleName();
   String getLastName();
}
Run Code Online (Sandbox Code Playgroud)

并添加一个方法到你的Repository

@Repository
public interface StudentDetailsRepository extends JpaRepository<StudentDetail, Integer> {
   StudentDetailProjection get...(...);
}
Run Code Online (Sandbox Code Playgroud)

Spring 将自动对该接口进行子类化,并要求 JPA 执行一个查询,该查询将仅提取指定的字段。

  1. class基于-的投影的
    工作方式与基于接口的投影几乎相同,但不需要代​​理和子类化,因为您为 Spring 提供了一个具体的类。

public class StudentDetailProjection {
   private final String getFirstName;
   private final String getMiddleName;
   private final String getLastName;

   public StudentDetailProjection(
      final String getFirstName,
      final String getMiddleName,
      final String getLastName,
   ) {...}

   // Getters
}
Run Code Online (Sandbox Code Playgroud)

文档更加深入。

另外,必须阅读JPA 大师 Vlad Mihalcea 的这篇博文。


该方法可能看起来大约像

@Query("select new your.package.StudentDetailProjection(d.firstName, d.middleName, d.lastName) from StudentDetail d where month(d.dateOfBirth) = ?1")
List<StudentDetailProjection> getStudentListBasedOnDateOfBirth(final int month);
Run Code Online (Sandbox Code Playgroud)

这将遵循具体class选项 (2),因为需要构造函数。