【问题标题】:How to select few fields from a Entity in Spring Boot using Spring Data?如何使用 Spring Data 从 Spring Boot 中的实体中选择几个字段?
【发布时间】:2019-08-21 08:11:30
【问题描述】:

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

实体

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 类的返回类型是实体类型 StudentDetail 。仅从中选择几个字段将导致错误。所以,我想知道我应该在repo/servicecontroller 类中进行哪些更改(假设只有类的返回类型会改变)?

【问题讨论】:

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


【解决方案1】:

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

以您的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 更深入。

另外,必读的是 JPA 大师 Vlad Mihalcea 的 this 博客文章。


该方法可能看起来很像

@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),因为需要构造函数。

【讨论】:

  • 所以接口只包含我在输出 JSON 中想要的那些 getter 吗?另外,您能否解释一下存储库代码更改。方法应该包含什么?
  • @BoudhayanDev 这一切都在文档中进行了解释,包括示例、解释和一切。阅读并尝试一下。
  • @JBNizet 我还是添加了这个例子。有多种方法可以做到这一点,Boudhayan Dev 可以阅读 Vlad Mihalcea 博客文章中详细介绍的所有内容。
  • @BoudhayanDev 我更新了答案。看看底部。这称为构造函数表达式。不过,请查看我链接的博客文章。
  • @BoudhayanDev 绝对不是。 Query 注释中的“新”部分只是告诉 JPA 它必须实例化将这些值传递给构造函数的类。投影不是实体。
猜你喜欢
  • 1970-01-01
  • 2017-05-20
  • 2020-05-11
  • 2020-01-14
  • 2019-02-14
  • 2015-09-01
  • 2021-08-31
  • 1970-01-01
  • 2019-09-21
相关资源
最近更新 更多