当前位置: 首页 > 知识库问答 >
问题:

Spring数据Rest -按嵌套属性排序

袁亦
2023-03-14

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

我有以下课程:

@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

参数ort=name.lastNameort=nameLastName也不起作用。

我是否形成了错误的Rest请求,或者缺少一些配置

谢谢大家!


共有3个答案

裴钧
2023-03-14

从Spring Data REST留档:

不支持按可链接关联(即指向顶级资源的链接)进行排序。

https://docs.spring.io/spring-data/rest/docs/current/reference/html/#paging-and-sorting.sorting

我发现的另一种选择是使用@ResResources(导出=false)。这是无效的(尤其是对于传统的Spring Data REST项目),因为避免资源/实体将被加载HTTP链接:

JacksonBinder
BeanDeserializerBuilder updateBuilder throws
 com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of ' com...' no String-argument constructor/factory method to deserialize from String value

我尝试在注释的帮助下通过可链接关联激活排序,但没有成功,因为我们总是需要覆盖< code > jacksonmappingawaresortransfer的< code>mappPropertyPath方法。SortTranslator检测注释:

            if (associations.isLinkableAssociation(persistentProperty)) {
                if(!persistentProperty.isAnnotationPresent(SortByLinkableAssociation.class)) {
                    return Collections.emptyList();
                }
            }

注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SortByLinkableAssociation {
}

在项目中将关联标记为@SortByLinkableAssociation:

@ManyToOne
@SortByLinkableAssociation
private Name name;

真的,我没有找到一个明确而成功的解决方案来解决这个问题,但决定公开它,让我们考虑一下,甚至Spring团队也考虑在下一个版本中加入。

慕和惬
2023-03-14

我通过它进行了调试,它看起来像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.0版本;这个问题似乎在所有版本中都存在。

艾善
2023-03-14

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

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

    ...
}

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

稍后编辑:另一个缺点是我们无法对客户端隐藏嵌入的属性。在我最初的答案中,我建议我们可以添加@JsonIgnore,但显然这打破了这种排序。

 类似资料:
  • 我有一个实体如下 使用Spring Data Rest(Gosling Release Train),我可以指定 用于对名称进行升序排序。现在,我需要按numberOfHands降序和name升序排序。我可以指定 谢谢!

  • 我正在尝试按地理距离对具有嵌套地理点映射的索引进行排序。 这是我的简化映射: 这里,每个组织可以有几个地点点。 文档: 这是我的查询(PHP数组): 预期结果 : 我希望按geo_point排序资源(检查每个位置,然后检查某个位置是否靠近给定的纬度/经度)

  • 假设我有那些DTO: 在我的存储库中,我使用这些DTO作为投影进行查询: 我可以使用这个repo很好地访问ForumDTO中的id、name,但对于lasthread,它只返回null。我试过作为最后一个线程。Id、lastThread\u Id、lastThreadId均无效。

  • 我正在尝试查询spring data elasticsearch存储库中的嵌套属性。我的存储库如下所示: 域对象Person和Address(无getter/setter)定义如下: 我的测试保存一个人的文档,并尝试使用repository方法读取它。但没有返回任何结果。以下是测试方法: spring data elasticsearch是否支持默认的spring数据查询生成?

  • 我想要编写一个Spring Data JPA存储库接口方法签名,它将允许我查找实体中具有嵌入对象属性的实体。有没有人知道这是否可能,如果可能,如何实现?

  • 我有两个使用分页和排序存储库定义的资源: 画廊/{id} 一般来说,这两种资源的分页都是根据使用的存储库类型提供的。 画廊本身包含一个图像列表 我现在可以通过 画廊/1/图片 是否也可以为这些子列表启用分页?或者,处理这些大列表的REST样式是什么。 事先谢谢你,圭多