【问题标题】:Spring Data JPA exclude properties for specific RequestMappingSpring Data JPA 排除特定 RequestMapping 的属性
【发布时间】:2019-05-31 04:57:39
【问题描述】:

考虑到 PetClinic Res API 的经典示例,我有 2 个 REST 调用:

  • GET /petclinic/owners
  • GET /petclinic/owners/[SOME_ID]

第一次调用返回所有所有者(详细),第二次返回特定所有者详细信息。

在这两种情况下,每个所有者对象都包含所有者的基本详细信息以及宠物列表,每个宠物还包含访问次数

如果我想返回没有宠物的所有者列表并访问我的 findAll(第一个 API)调用的详细信息并为第二次调用提供完整的详细信息,最好的方法是什么??

我已经探索了 custom serializer 实现,但我不想在实体级别应用它。如果我使用杰克逊手动准备 JSON,它仍然会进行数据库调用!在第一次 REST 调用的情况下,我基本上想避免不必要的数据库获取

【问题讨论】:

  • 我认为你必须定义主人和宠物之间的惰性关联
  • @GovindParasha 你在说“fetchType”吗? OneToMany 关联默认情况下已经是 LAZY 了!!
  • 我曾经通过 orika mapper 转换成 DTO 然后返回
  • 如果您希望 Spring Data 仅在后台处理从数据库中加载必要的属性,那么projections 是您的最佳选择
  • @GovindParashar 您对 Orika 的评论一开始没有意义,但现在当我意识到“mapstruct”时,您的回答也很有意义。

标签: spring hibernate spring-mvc spring-data-jpa spring-rest


【解决方案1】:

您需要将数据库对象与您返回的内容分开。由于宠物在 LAZY OneToMany 关联的后面,因此当您在 findAll 中获取列表时,它们不会被获取...但是当您将实体对象传递到将(可能)调用给定对象的每个 getter 的 serailizing 库时,它们会被获取.

因此,现在您要么以某种方式修改序列化过程,使其不会调用错误的 getter 并触发 fetch...您可以使用现有的映射库来简化该过程(即 mapstruct)。

您甚至可以将这些 DTO 作为 API 模型作为应用程序的适当部分 - 将前端 API 从数据库中分离出来,以便您可以更轻松地对其进行外观更改(不存储在数据库中的字段,重命名不存储在数据库中的字段) t 破坏您的 JPQL,可能会生成文档)

【讨论】:

  • 感谢您的解释。我对春天的世界很陌生。在您回答之后,我探索了 mapstruct 并让事情正常进行。谢谢男人。
【解决方案2】:

如果您真的想这样做,我认为您需要返回 Object 而不是确切的 Owner 实体。 如果您希望 DB 层也高效,即只获取您需要的属性,您应该创建一个函数,该函数接受一个 List 包含值是您需要的属性,并且该函数将返回一个 Object 然后发送它你的 API。 所以在你的情况下,它会是这样的。

//DAO 
public List<Object> findAll(List<String> fieldsNeeded) {
     String hql = "SELECT ";

     for (String field: fieldsNeeded) {
         hql += field + " ";
     }

     hql += "FROM //your table name";

     // create query and all those stuff;
     // return the result
}

//controller
@GetMapping("/petclinic/owners")
public List<Object> getOwners(//your parameters) {
     // (lets skip service layer)
     // then you need to prepare the list of needed properties
     // including checking if the properties do exsit in the table etc...
     // which also returns an object;

     List<String> fieldsNeeded = new ArrayList<String>();

     // add all the fieldnames;

     return ownerDao.findAll(fieldsNeeded);
}

此外,如果您有一个包含大量属性的巨大表,您应该使用 StringBuilder 中的 .append() 函数更改“hql += ...”,如果需要的属性数量太大,您应该告诉函数不要获取传递的属性,而是获取未传递的属性。


所以我发现你实际上不能用 REST 返回一个对象。 因此,如果您需要发送一个对象,我建议您在获得 DAO 层的结果后在服务层中添加一个注入步骤,您将对象中的所有字段设置为实体,它应该可以工作很好。

【讨论】:

  • 这是有道理的,但它需要大量的手动工作。我想使用 mapstruct 将是节省手动转换工作的好主意。感谢您的建议和解释。
猜你喜欢
  • 1970-01-01
  • 2021-11-13
  • 2015-01-24
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 2016-01-23
  • 2020-02-01
  • 2017-07-10
相关资源
最近更新 更多