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. I followed this workaround and got stuck with implementing the findBy query.
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:
@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:
@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.
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. 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);
That means: what you did should work, except the case your Device
class has a field 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]
This looks like your class User
does not have a field called 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)
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. 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
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 "_"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With