2017-07-22 73 views
11

Mam model:Wiosna danych URI zasobów REST klienta pracuje dla strun, ale nie za długo

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

chciałbym używać externalId jak mój identyfikator zasobu:

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

Jeśli externalId jest String, to działa dobrze. Ale ponieważ jest to numer (Long)

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

podczas wywoływania: /myModels/1 uzyskać:

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] 
    ... 

oddzielnym zwyczaj EntityLookupSupport<MyModel> prace klasy komponentów.

Czy brakuje mi czegoś, aby zadziałało dla Long używając referencji metod w moim RepositoryRestConfigurerAdapter?

+0

Jaki jest typ bazowej kolumny bazy danych? Czy kolumna jest łańcuchem? – Ben

+0

@Ben Typ kolumny bazy danych: int, Baza danych: MySQL. Jeśli typ był String, działa (nie jest potrzebny konwerter, pole modelu to String zamiast Long). Potrzebuję go do pracy z typem int (ograniczenia klucza obcego). – rizjoj

+0

Co, jeśli wywołasz '/ myModels/1L' zamiast'/myModels/1'? Może to być problem z serializacją. –

Odpowiedz

0

Spróbuj dodać do swojej klasy RepositoryEntityLookupConfig:

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

Dodano. Nadal dostaję "java.lang.ClassCastException: java.lang.String nie można przesłać do java.lang.Long". – rizjoj

0

Czy naprawdę trzeba ustawić konfigurację przez siebie? Można spróbować użyć wiosna-boot automatyczną konfigurację dodając @RepositoryRestResource adnotacji

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

dodać także @Entity na swojej klasie modelu

@Entity 
public class MyModel { 
    @Id 
    private Long id; 
    @Column(name = "EXTERNAL_ID") 
    // Column annotation is not required if you respect case-sensitive 
    private Long externalId; 
    // Getters, setters 
} 
+0

Nie działa dla mnie. Dodanie '@ RepositoryRestResource' na MyRepository (podczas usuwania konfiguracji) daje taki sam efekt jak domyślny' findById'. Model jest już opisany z @Entity, a kolumna nie wymaga adnotacji (w przeciwnym razie findByExternalId działa). – rizjoj

0

Podpis metody, którą próbujesz wywołać wydaje być:

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

nie jestem bardzo obeznany z Java 8 jednak nie widzę jak MyModel::getExternalId można robić niezbędną konwersję.

Chciałbym wypróbować coś takiego, co bez wątpienia ma "uproszczoną" alternatywną konstrukcję Java 8.

@Configuration 
static class RepositoryEntityLookupConfig extends RepositoryRestConfigurerAdapter { 
    @Override 
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration configuration) { 

    Converter<String, Long> converter = new Converter(){ 
     public Long convert(String source){ 
      return Long.parseLong(source); 
     } 
    }; 

    configuration 
       .withEntityLookup() 
        .forRepository(MyRepository.class, converter, MyRepository::findByExternalId); 
    } 
}