Spring Data JPA排除特定RequestMapping的属性

时间:2019-01-04 15:39:00

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

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

  • 获取/ petclinic / owners
  • 获取/ petclinic / owners / [SOME_ID]

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

在两种情况下,每个所有者对象都包含所有者基本详细信息以及宠物列表,每个 pet 进一步包含访问

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

我已经研究了自定义序列化程序的实现,但是我不想将其应用于实体级别。如果我使用杰克逊手动准备JSON,它仍然会进行数据库调用!我基本上是想避免在进行第一次REST调用

时不必要的数据库获取

2 个答案:

答案 0 :(得分:1)

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

因此,现在您要么以某种方式修改序列化过程,以使其不会调用错误的getter并触发提取...,或者您使一个映射器将实体转换为仅具有所需字段的DTO,然后对其进行序列化。您可以使用现有的映射库来简化该过程(即mapstruct)。

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

答案 1 :(得分:0)

如果您确实想这样做,我认为您需要返回Object而不是确切的Owner实体。 并且,如果您也希望DB层也高效(仅获取所需的属性),则应创建一个函数,该函数接受一个List,该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返回对象。 因此,如果您需要发送jsut一个对象,我建议您做的是在获得DAO层的结果后,在Service层中添加一个注入步骤,将Object中的所有字段设置为Entity,它应该可以工作很好。