Spring Data Rest - 按嵌套属性排序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Data Rest - 按嵌套属性排序相关的知识,希望对你有一定的参考价值。

我有一个使用Spring Boot 1.5.1和Spring Data Rest的数据库服务。我将我的实体存储在mysql数据库中,并使用Spring的PagingAndSortingRepository通过REST访问它们。我发现this声明支持按嵌套参数排序,但我找不到按嵌套字段排序的方法。

我有这些课程:

@Entity(name = "Person")
@Table(name = "PERSON")
public class Person {
    @ManyToOne
    protected Address address;

    @ManyToOne(targetEntity = Name.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumn(name = "NAME_PERSON_ID")
    protected Name name;

    @Id
    protected Long id;

    // Setter, getters, etc.
}

@Entity(name = "Name")
@Table(name = "NAME")
public class Name{

    protected String firstName;

    protected String lastName;

    @Id
    protected Long id;

    // Setter, getters, etc.
}

例如,使用该方法时:

Page<Person> findByAddress_Id(@Param("id") String id, Pageable pageable);

调用URI http://localhost:8080/people/search/findByAddress_Id?id=1&sort=name_lastName,desc时,Spring完全忽略sort参数。

参数sort = name.lastName和sort = nameLastName也不起作用。

我是否构成了Rest请求错误,或者缺少某些配置?

谢谢!

答案

我通过调试,看起来像Alan提到的问题。

我找到了可能有用的解决方法:

创建自己的控制器,注入您的仓库和可选的投影工厂(如果您需要投影)。实现get方法以委托对您的存储库的调用

 @RestController
 @RequestMapping("/people")
 public class PeopleController {

    @Autowired
    PersonRepository repository;

    //@Autowired
    //PagedResourcesAssembler<MyDTO> resourceAssembler;

    @GetMapping("/by-address/{addressId}")
    public Page<Person> getByAddress(@PathVariable("addressId") Long addressId, Pageable page)  {

        // spring doesn't spoil your sort here ... 
        Page<Person> page = repository.findByAddress_Id(addressId, page)

        // optionally, apply projection
        //  to return DTO/specifically loaded Entity objects ...
        //  return type would be then PagedResources<Resource<MyDTO>>
        // return resourceAssembler.toResource(page.map(...))

        return page;
    }

}

这适用于2.6.8.RELEASE;问题似乎在所有版本中。

另一答案

我找到的解决方法是创建一个额外的只读属性,仅用于排序目的。基于上面的例子:

@Entity(name = "Person")
@Table(name = "PERSON")
public class Person {

    // read only, for sorting purposes only
    // @JsonIgnore // we can hide it from the clients, if needed
    @RestResource(exported=false) // read only so we can map 2 fields to the same database column
    @ManyToOne
    @JoinColumn(name = "address_id", insertable = false, updatable = false) 
    private Address address;

    // We still want the linkable association created to work as before so we manually override the relation and path
    @RestResource(exported=true, rel="address", path="address")
    @ManyToOne
    private Address addressLink;

    ...
}

建议的解决方法的缺点是我们现在必须明确复制我们想要支持嵌套排序的所有属性。

LATER EDIT:另一个缺点是我们无法隐藏客户端的嵌入属性。在我原来的回答中,我建议我们可以添加@JsonIgnore,但显然这会破坏排序。

以上是关于Spring Data Rest - 按嵌套属性排序的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data Rest - 按多个属性排序

Spring Data Rest with Spring Security - 按当前用户查找所有内容

如何按角色限制对 Spring Data REST 投影的访问?

如何让Spring的Data Rest Repository按名称而不是id来检索数据

Spring Data REST 的 QueryDSL 集成,用于查询实体中集合映射的子属性

使用 Spring Data REST,为啥 @Version 属性成为 ETag 并且不包含在表示中?