我有一个与this question非常相似的问题,但并不完全相同。我想使用基于字符串的外部id,所以在EntityLookup
中设置自定义the documentation配置。
这适用于GET
,POST
和DELETE
,但PUT
失败了ConversionFailedException
。
我可以使用以下最小配置重现错误,以使用username
作为要查找的字段:
user.Java
@Entity
public class User {
@Id
private Long id;
private String username;
private String fullName;
}
user repo.Java
@RepositoryRestResource(exported = true)
public interface UserRepo extends PagingAndSortingRepository<User, Long> {
Optional<User> findByUsername(String username);
}
spring data rest customization.Java
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.withEntityLookup()
.forRepository(UserRepo.class, User::getUsername, UserRepo::findByUsername);
}
}
我可以然后POST
新记录并通过GET /users/username
获取它们,但PUT
到现有资源会出现以下错误:
o.s.d.r.w.RepositoryRestExceptionHandler : Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'username'; nested exception is java.lang.NumberFormatException: For input string: "username"
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'username'; nested exception is java.lang.NumberFormatException: For input string: "username"
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:46) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.data.mapping.model.ConvertingPropertyAccessor.convertIfNecessary(ConvertingPropertyAccessor.java:123) ~[spring-data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.data.mapping.model.ConvertingPropertyAccessor.setProperty(ConvertingPropertyAccessor.java:61) ~[spring-data-commons-2.1.4.RELEASE.jar:2.1.4.RELEASE]
at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.lambda$resolveArgument$3(PersistentEntityResourceHandlerMethodArgumentResolver.java:149) ~[spring-data-rest-webmvc-3.1.4.RELEASE.jar:3.1.4.RELEASE]
at java.base/java.util.Optional.ifPresent(Optional.java:183) ~[na:na]
at org.springframework.data.rest.webmvc.config.PersistentEntityResourceHandlerMethodArgumentResolver.resolveArgument(PersistentEntityResourceHandlerMethodArgumentResolver.java:146) ~[spring-data-rest-webmvc-3.1.4.RELEASE.jar:3.1.4.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126) ~[spring-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
那绝对是一个错误。
这是因为PUT repository/{id}
端点也可用于创建具有给定id的新实体。因此,在PUT请求期间,它会尝试将URL中的id放入对象的id属性中。但是 - 因为你有一个独特的EntityLookup - URL片段不是实体的id属性......
似乎作者只是忘了处理这个案子。当我看到源代码时,我看不到任何简单的解决方法。
我认为PATCH请求仍然有效,所以如果你可以避免使用PUT请求,那么这可能是一个解决方案。
我个人不喜欢这整个EntityLookup功能。 (事实证明:听起来不错,不起作用:))我认为URL的id片段应该是实体的实际id。也许它并没有违反REST原则,但我仍觉得不合适。
如果您想通过用户名获取用户,则可以随时使用users / search / findByUsername端点,之后如果您想稍后通过PUT请求修改对象,您将在响应中拥有_self链接。