Spring Data REST自定义资源URI适用于String但不适用于Long

时间:2017-07-22 09:07:34

标签: spring spring-data-jpa spring-data-rest

我有一个模特:

public class MyModel {
    @Id private Long id;
    private Long externalId;
    // Getters, setters
}

我想使用externalId作为我的资源标识符:

@Configuration
static class RepositoryEntityLookupConfig extends RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration configuration) {
        configuration
                .withEntityLookup()
                    .forRepository(MyRepository.class, MyModel::getExternalId, MyRepository::findByExternalId);
    }
}

如果externalIdString,则可以正常使用。但因为它是一个数字(Long

public interface MyRepository extends JpaRepository<MyModel, Long> {
    Optional<MyModel> findByExternalId(@Param("externalId") Long externalId);
}

调用时:/myModels/1我得到:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at org.springframework.data.rest.core.config.EntityLookupConfiguration$RepositoriesEntityLookup.lookupEntity(EntityLookupConfiguration.java:213) ~[spring-data-rest-core-2.6.4.RELEASE.jar:na]
    at org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory$UnwrappingRepositoryInvoker.invokeFindOne(UnwrappingRepositoryInvokerFactory.java:130) ~[spring-data-rest-core-2.6.4.RELEASE.jar:na]
    at org.springframework.data.rest.webmvc.RepositoryEntityController.getItemResource(RepositoryEntityController.java:524) ~[spring-data-rest-webmvc-2.6.4.RELEASE.jar:na]
    at org.springframework.data.rest.webmvc.RepositoryEntityController.getItemResource(RepositoryEntityController.java:335) ~[spring-data-rest-webmvc-2.6.4.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
    ...

单独的自定义EntityLookupSupport<MyModel>组件类可用。

我在Long中使用方法引用错过了一些让RepositoryRestConfigurerAdapter工作的内容吗?

4 个答案:

答案 0 :(得分:0)

尝试将其添加到RepositoryEntityLookupConfig班级:

@Override
public void configureConversionService(ConfigurableConversionService conversionService) {
    conversionService.addConverter(String.class, Long.class, Long::parseLong);
    super.configureConversionService(conversionService);
}

答案 1 :(得分:0)

您真的需要自己设置配置吗?您可以尝试通过添加@RepositoryRestResource注释来使用spring-boot自动配置

function.grad

还在模型类上添加@Entity

@RepositoryRestResource(collectionResourceRel = "myModels", path = "myModels")
public interface MyRepository extends JpaRepository<MyModel, Long> {
        Optional<MyModel> findByExternalId(@Param("externalId") Long externalId);
}

答案 2 :(得分:0)

您尝试调用的方法的签名似乎是:

forRepository(Class<R> type, Converter<T,ID> identifierMapping, 
         EntityLookupRegistrar.LookupRegistrar.Lookup<R,ID> lookup)

我不知道MyModel::getExternalId如何进行必要的转换。

我会尝试以下内容:

@Configuration
static class RepositoryEntityLookupConfig extends RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration configuration) {
    configuration
                .withEntityLookup()
                    .forRepository(MyRepository.class, Long::parseLong, MyRepository::findByExternalId);
    }
}

答案 3 :(得分:0)

显然,默认的BackendIdConverter(参见DefaultIdConverter)对ID转换没有任何作用,另一方面,Spring Data Rest不能使用存储库ID类型。因此,您必须自己进行转换或配置自定义ID转换器bean,例如:

@Bean
public BackendIdConverter myModelBackendIdConverter() {
  return new BackendIdConverter() {

    @Override
    public Serializable fromRequestId(final String id, final Class<?> entityType) {
      return Optional.ofNullable(id).map(Long::parseLong).orElse(null);
    }

    @Override
    public boolean supports(final Class<?> delimiter) {
      return MyModel.class.isAssignableFrom(delimiter);
    }

    @Override
    public String toRequestId(final Serializable id, final Class<?> entityType) {
      return Optional.ofNullable(id).map(Object::toString).orElse(null);
    }
  };
}

另见:

  • BackendIdHandlerMethodArgumentResolver
  • @BackendId