我有一个使用Spring-data-rest生成REST接口的SpringBoot项目,并且我试图允许对嵌套资源进行分页。我遵循了此变通办法并被困于实现findBy查询。
我具有以下设备实体:
@Entity @Table(name = "devices") public class Device extends ResourceSupport { ... @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; }
我需要使用userId查询它:
@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字段。
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!" }
看来我在错误地使用查询?
请看一下文档。
如上例所示,属性表达式只能引用被管实体的直接属性。在查询创建时,您已经确保已解析的属性是托管域类的属性。但是,您也可以通过遍历嵌套属性来定义约束。假设一个人的地址带有邮政编码。在这种情况下,方法名称为
List<Person> findByAddressZipCode(ZipCode zipCode);
[…]尽管这在大多数情况下都可行,但是算法可能会选择错误的属性。假设Person类也具有addressZip属性。该算法将在第一个拆分回合中匹配,并且本质上选择错误的属性,最后失败(因为addressZip的类型可能没有代码属性)。要解决这种歧义,您可以在方法名称中使用_手动定义遍历点。因此,我们的方法名称将最终如下所示:
List<Person> findByAddress_ZipCode(ZipCode zipCode);
这意味着:您所做的应该工作,除非您的Device班级有一个field userId。
Device
您向我们展示的异常是原始问题中的以下内容。
在此ManagedType [com.example.User]上找不到具有给定名称[id]的Attribute
看来您的课程User没有名为的字段id。由于您没有向我们展示此类的代码,因此我无法告知您是否属于这种情况。(确保您User在存储库中导入了正确的类)
User
id
问题已更新,因此另一个答案存在另一个错误
现在的问题是,您将User对象传递给存储库方法,但按ID进行了过滤。只需将第一个参数更改为用户标识的数据类型。我认为应该可以。
假设id的类型是int该方法可能看起来像这样
int
Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);