我遇到的问题与this question非常相似,但不完全相同。我想使用基于字符串的外部ID,因此请像在the documentation中那样设置自定义EntityLookup
。
这对于GET
,POST
和DELETE
来说非常有用,但是PUT
失败,出现ConversionFailedException
。
我可以使用以下最小配置重现错误,以使用username
作为要查找的字段:
User.java
@Entity
public class User {
@Id
private Long id;
private String username;
private String fullName;
}
UserRepo.java
@RepositoryRestResource(exported = true)
public interface UserRepo extends PagingAndSortingRepository<User, Long> {
Optional<User> findByUsername(String username);
}
SpringDataRestCustomization.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]
答案 0 :(得分:0)
那绝对是一个错误。
发生这种情况是因为PUT repository/{id}
端点也可以用于创建具有给定ID的新实体。
因此,在PUT请求期间,它将尝试将URL中的id放入对象的id属性中。但是-由于您具有唯一的EntityLookup-URL片段不是实体的ID属性...
看来作者只是忘了处理此案。而且,当我查找源代码时,我看不到任何简单的解决方法。
我认为PATCH请求仍然可以使用,因此,如果您可以避免使用PUT请求,那么这可能是一个解决方案。
我个人不喜欢整个EntityLookup功能。 (结果是:听起来不错,不起作用:))我认为URL的id片段应该是实体的实际ID。 也许它没有违反REST原则,但我仍然觉得不合适。
相反,如果您想通过用户名来获取用户,则可以随时使用users / search / findByUsername端点,然后,如果您想通过PUT请求修改对象,则在响应中将具有_self链接。以后。