Spring 数据 REST findBy 嵌套实体
Spring data REST findBy nested entity
我有一个 Spring 启动项目,使用 Spring-data-rest 来生成我的 REST 接口,我正在尝试允许对嵌套资源进行分页。我按照这个 workaround 执行了 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
字段。
但是,现在我收到以下异常:
{
"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!"
}
看来我使用的查询有误?
尝试
Page<Device> findByUser_Id(@Param("user") User user, Pageable pageable);
由于您正在 DeviceRepository 中创建一个方法,并且您希望在嵌套字段 (user.id) 上进行搜索,因此您需要使用“_”引用它
请看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. 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. 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).
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);
这意味着:您所做的应该有效,除非您的 Device
class 有一个字段 userId
.
您向我们展示的异常是原始问题中的以下内容。
Unable to locate Attribute with the the given name [id] on this ManagedType [com.example.User]
您的 class User
似乎没有名为 id
的字段。由于您没有向我们展示此 class 的代码,我无法判断是否是这种情况。 (确保您在存储库中导入了正确的 User
class)
问题已更新,因此另一个答案存在另一个错误
现在的问题是您将 User
对象传递给您的存储库方法,但按 ID 进行过滤。只需将第一个参数更改为用户 ID 的数据类型。我认为这应该有效。
假设 id 的类型是 int
该方法可能如下所示
Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);
我有一个 Spring 启动项目,使用 Spring-data-rest 来生成我的 REST 接口,我正在尝试允许对嵌套资源进行分页。我按照这个 workaround 执行了 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
字段。
但是,现在我收到以下异常:
{
"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!"
}
看来我使用的查询有误?
尝试
Page<Device> findByUser_Id(@Param("user") User user, Pageable pageable);
由于您正在 DeviceRepository 中创建一个方法,并且您希望在嵌套字段 (user.id) 上进行搜索,因此您需要使用“_”引用它
请看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. 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. 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). 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);
这意味着:您所做的应该有效,除非您的 Device
class 有一个字段 userId
.
您向我们展示的异常是原始问题中的以下内容。
Unable to locate Attribute with the the given name [id] on this ManagedType [com.example.User]
您的 class User
似乎没有名为 id
的字段。由于您没有向我们展示此 class 的代码,我无法判断是否是这种情况。 (确保您在存储库中导入了正确的 User
class)
问题已更新,因此另一个答案存在另一个错误
现在的问题是您将 User
对象传递给您的存储库方法,但按 ID 进行过滤。只需将第一个参数更改为用户 ID 的数据类型。我认为这应该有效。
假设 id 的类型是 int
该方法可能如下所示
Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);