简体   繁体   English

Spring数据REST findBy嵌套实体

[英]Spring data REST findBy nested entity

I have a Spring Boot project using Spring-data-rest for generating my REST interface and I am trying to allow pagination for nested resources. 我有一个使用Spring-data-rest的Spring Boot项目来生成我的REST接口,我试图允许嵌套资源的分页。 I followed this workaround and got stuck with implementing the findBy query. 我遵循这个解决方法,并坚持实现findBy查询。

I have the following Device entity: 我有以下设备实体:

@Entity
@Table(name = "devices")
public class Device extends ResourceSupport {

  ...

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "user_id")
  private User user;
}

I need to query it using userId: 我需要使用userId查询它:

@RequestMapping(path = "/users/{id}/devices", method = RequestMethod.GET)
public ModelAndView getUserDevices(@PathVariable Integer id) {
    return new ModelAndView("forward:/devices/search/findByUserId?userId=" + id);
}

So I created the following method in my DeviceRepository: 所以我在DeviceRepository中创建了以下方法:

@Repository
public interface DeviceRepository extends JpaRepository<Device, Long> {

  @PreAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(#user, authentication)")
  Page<Device> findByUserId(@Param("user") User user, Pageable pageable);

}

But I am getting the following exception when trying to send request to this endpoint: 但是在尝试向此端点发送请求时,我收到以下异常:

Unable to locate Attribute  with the the given name [id] on this ManagedType [com.example.User]

Does anyone have some suggestion what I am doing wrong? 有没有人有一些建议我做错了什么?

EDIT: Thank you for your responses, I changed the method to 编辑:谢谢你的回复,我改变了方法

Page<Device> findByUser_UserId(@Param("user") User user, Pageable pageable);

My user entity contains a userId field. 我的用户实体包含userId字段。

However, now I am getting the following exception: 但是,现在我收到以下异常:

{
    "cause": {
        "cause": {
            "cause": null,
            "message": "Cannot resolve URI 1. Is it local or remote? Only local URIs are resolvable."
        },
        "message": "Failed to convert from type [java.net.URI] to type [@org.springframework.data.repository.query.Param com.example.User] for value '1'; nested exception is java.lang.IllegalArgumentException: Cannot resolve URI 1. Is it local or remote? Only local URIs are resolvable."
    },
    "message": "Failed to convert 1 into me.originalsin.user.model.User!"
}

So it seems I am using the query wrongly? 所以我似乎错误地使用了查询?

Please have a look at the docs . 请查看文档

Property expressions can refer only to a direct property of the managed entity, as shown in the preceding example. 属性表达式只能引用被管实体的直接属性,如前面的示例所示。 At query creation time you already make sure that the parsed property is a property of the managed domain class. 在查询创建时,您已确保已解析的属性是托管域类的属性。 However, you can also define constraints by traversing nested properties. 但是,您也可以通过遍历嵌套属性来定义约束。 Assume a Person has an Address with a ZipCode. 假设一个人有一个带ZipCode的地址。 In that case a method name of 在这种情况下,方法名称为

List<Person> findByAddressZipCode(ZipCode zipCode);

[...] Although this should work for most cases, it is possible for the algorithm to select the wrong property. [...]虽然这应该适用于大多数情况,但算法可能会选择错误的属性。 Suppose the Person class has an addressZip property as well. 假设Person类也有一个addressZip属性。 The algorithm would match in the first split round already and essentially choose the wrong property and finally fail (as the type of addressZip probably has no code property). 该算法将在第一个拆分轮中匹配,并且基本上选择了错误的属性并最终失败(因为addressZip的类型可能没有代码属性)。 To resolve this ambiguity you can use _ inside your method name to manually define traversal points. 要解决这种歧义,可以在方法名称中使用_来手动定义遍历点。 So our method name would end up like so: 所以我们的方法名称最终会像这样:

List<Person> findByAddress_ZipCode(ZipCode zipCode);

That means: what you did should work, except the case your Device class has a field userId . 这意味着:除了您的Device类具有字段userId之外,您所做的工作应该有效。

The exception you showed to us was the following in the original question. 您向我们展示的例外是原始问题中的以下内容。

Unable to locate Attribute with the the given name [id] on this ManagedType [com.example.User] 无法在此ManagedType [com.example.User]上找到具有给定名称[id]的Attribute

This looks like your class User does not have a field called id . 这看起来像您的类User没有名为id的字段。 Since you did not show us the code of this class i cant tell if that's the case or not. 既然你没有向我们展示这个类的代码我就不知道是不是这样。 (Make sure that you imported the correct User class in your repository) (确保在存储库中导入了正确的User类)

Question has been updated and therefore ANOTHER error exists with ANOTHER answer 问题已更新,因此另一个答案存在另一个错误

The problem now is that you pass a User object to your repository method but filter by an id. 现在的问题是您将User对象传递给存储库方法,但按ID过滤。 Just change the first parameter to the datatype of the user id. 只需将第一个参数更改为用户标识的数据类型即可。 I think that should work. 我认为这应该有效。

Assuming the type of id is int the method could look like this 假设id的类型为int该方法可能如下所示

Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);

Try 尝试

 Page<Device> findByUser_Id(@Param("user") User user, Pageable pageable);

Since you are creating a method in DeviceRepository, and you want to search on a nested filed(user.id), You need to reference it using "_" 由于您要在DeviceRepository中创建方法,并且要在嵌套字段(user.id)上进行搜索,因此需要使用“_”进行引用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM