简体   繁体   English

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

[英]How to select few fields from a Entity in Spring Boot using Spring Data?

I have a use case where I want to display the contents of an entity but hide certain fields. 我有一个用例,其中我想显示实体的内容,但隐藏某些字段。 My entity is as follows - 我的实体如下-

Entity 实体

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

It has many other properties as well which I am not showing here. 它还具有许多其他属性,我在这里没有显示。

Repository - 储存库-

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

}

Service class - 服务等级-

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

And there is a controller class which calls the Service class with a month parameter to filter the data set. 还有一个控制器类,该类通过一个month参数调用Service类来过滤数据集。

What I want to do is modify the query in Repository class and include only the firstname , middleName and lastName property. 我想做的是修改Repository类中的查询,并仅包含firstnamemiddleNamelastName属性。 The Repository class should hide the dateOfBirth field. Repository类应隐藏dateOfBirth字段。 I realise that the following query will return the filtered items - 我意识到以下查询将返回过滤后的项目-

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

However, the return type of the Repository class is of Entity Type StudentDetail . 但是, Repository类的返回类型为Entity Type StudentDetail。 Selecting only few fields from it will result in error. 从中仅选择几个字段将导致错误。 So, I want to know what changes should I make in the repo / service and controller class (assuming only return types of the classes will change ) ? 因此,我想知道应该对repo / servicecontroller类进行哪些更改(假设仅返回类的类型会更改)?

This is called projection , and Spring offers you two ways to accomplish it. 这就是所谓的projection ,Spring为您提供了两种方法来实现它。
Keep in mind this exists in JPA terms, not only in Spring. 请记住,这不仅以Spring的形式存在于JPA术语中。

Taking your Repository as a starting point 以您的Repository为起点

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

we can use 我们可以用

  1. interface -based projection 基于interface的投影
    simply create an interface which represents the result you want to have 只需创建一个代表您想要的结果的接口

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

and add a method to your Repository 并向您的Repository添加方法

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

Spring will subclass that interface automatically and it will ask JPA to execute a query which will extract only the specified fields. Spring将自动对该接口进行子类化,它将要求JPA执行查询,该查询仅提取指定的字段。

  1. class -based projection 基于class的投影
    works in almost the same way as interface-based projection, but no proxying and sub-classing is necessary, as you're offering Spring a concrete 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 goes more in depth. 文档更深入。

Also, a must read is this blog post by Vlad Mihalcea, the master of JPA. 另外,必须阅读的是JPA的大师Vlad Mihalcea的这篇博客文章。


The method might look, approximately, like 该方法大概看起来像

@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);

This will go along the concrete class option (2), because a constructor is required. 这将沿着具体的class选项(2)进行,因为需要构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM