Spring Data REST findBy嵌套实体

7
我有一个使用Spring-data-rest生成REST接口的Spring Boot项目,我想允许为嵌套资源进行分页。我按照这个方法进行操作,在实现findBy查询时遇到了问题。
我有以下设备实体:
@Entity
@Table(name = "devices")
public class Device extends ResourceSupport {

  ...

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

我需要使用用户ID作为查询条件:

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

所以我在我的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);

}

但是当我尝试向此端点发送请求时,我遇到了以下异常:
Unable to locate Attribute  with the the given name [id] on this ManagedType [com.example.User]

有人能给我一些建议,我做错了什么吗?
编辑: 感谢您的回复,我已将方法更改为


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

我的用户实体包含一个userId字段。

然而,现在我遇到了以下异常:

{
    "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!"
}

所以看来我错误地使用了查询?
2个回答

7
请查看文档
属性表达式只能引用托管实体的直接属性,如上例所示。在查询创建时,您已经确保解析的属性是托管域类的属性。但是,您也可以通过遍历嵌套属性来定义约束条件。假设一个人有一个带有邮政编码的地址。在这种情况下,方法名称为
List<Person> findByAddressZipCode(ZipCode zipCode);

尽管这种方法对大多数情况都有效,但算法有可能选择错误的属性。假设Person类也有一个addressZip属性,那么在第一轮分割中算法就会匹配到这个属性,从而选择了错误的属性,并最终失败(因为addressZip的类型可能没有code属性)。为了解决这种歧义,您可以在方法名称中使用_来手动定义遍历点。因此,我们的方法名称最终会变成这样:
List<Person> findByAddress_ZipCode(ZipCode zipCode);

那意味着:你所做的应该有效,除非你的Device类有一个叫做userId的字段。
你向我们展示的异常来自原始问题,如下所示。

无法在此ManagedType [com.example.User]上找到具有给定名称[id]的属性

这看起来像是你的User类没有名为id的字段。由于你没有向我们展示这个类的代码,我无法确定是否是这种情况。(确保你在存储库中导入了正确的User类)
问题已经更新,因此存在另外一个错误和另外一个答案。
现在的问题是你将一个User对象传递给你的存储库方法,但是按照id进行过滤。只需将第一个参数更改为用户id的数据类型即可。我认为那应该可以工作。
假设id的类型是int,则该方法可能如下所示:
Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);

谢谢你的回答,对我非常有帮助。但是我得到了完全不同的异常。你可以看一下更新后的问题吗? - Smajl

2

请尝试

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

由于您正在在DeviceRepository中创建一个方法,而且您想要在一个嵌套的字段(user.id)上进行搜索,因此您需要使用"_"引用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接