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

时间:2019-03-30 16:27:25

标签: java spring spring-boot spring-mvc spring-data-jpa

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

实体

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;
}

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

存储库-

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

}

服务类-

public List<StudentDetail> getStudentBirthdayDetails(int month) {
        List<StudentDetail> StudentDetail = StudentDetailsRepository.getStudentListBasedOnDateOfBirth(month);
        return StudentDetail;
    }

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

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

select d.firstName, d.middleName, d.lastName from StudentDetail d where month(d.dateOfBirth) = ?1 

但是,Repository类的返回类型为Entity Type StudentDetail。从中仅选择几个字段将导致错误。因此,我想知道应该在repo / servicecontroller类中进行哪些更改(假设仅返回类的类型会更改)?

1 个答案:

答案 0 :(得分:2)

这称为 projection ,Spring提供了两种方法来实现它。
请记住,这不仅以Spring的形式存在于JPA术语中。

以您的Repository为起点

@Repository
public interface StudentDetailsRepository extends JpaRepository<StudentDetail, Integer> {
   ...
}

我们可以使用

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

public interface StudentDetailProjection {
   String getFirstName();
   String getMiddleName();
   String getLastName();
}

并将方法添加到您的Repository

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

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
}

Documentation更深入。

此外,必须阅读的是this博客,作者是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);

这将沿具体的class选项(2)进行,因为需要构造函数。