2015-03-31 14 views
13

È possibile specificare projection quando si chiama direttamente il metodo dell'archivio dati? Ecco il codice di repository - Nota non vorrei esporlo via REST, invece mi piacerebbe essere in grado di chiamare da un servizio o un controller:Come applicare le proiezioni Spring Data in un controller MVC Spring?

@RepositoryRestResource(exported = false) 
public interface UsersRepository extends PagingAndSortingRepository<User, Long> { 

    @Query(value = "SELECT u FROM User u WHERE ....") 
    public Page<User> findEmployeeUsers(Pageable p); 
} 

Poi in un controllore faccio questo:

@PreAuthorize(value = "hasRole('ROLE_ADMIN')") 
@RequestMapping(value = "https://stackoverflow.com/users/employee") 
public Page<User> listEmployees(Pageable pageable) { 
    return usersRepository.findEmployeeUsers(pageable); 
} 

C'è un modo per specificare projection per il metodo findEmployeeUsers quando viene chiamato direttamente come sopra?

Mi rendo conto che il codice sopra potrebbe sembrare strano per qualcuno ... sarebbe possibile esporre il repository tramite REST e inserire la cosa @PreAuthorize nel repository. Il controller del pensiero è il posto più adatto per i controlli di sicurezza: è più naturale e più semplice da testare.

Quindi, la cosa può essere passata in qualche modo in un metodo di deposito chiamato direttamente? projection?

risposta

36

No, non lo è, soprattutto perché le proiezioni vengono generalmente applicate al risultato dell'esecuzione di una query caso per caso. Pertanto sono attualmente progettati per essere applicati in modo selettivo ai tipi di dominio.

Come da ultimo Spring Data Fowler rilascio treno GA rilascio dell'infrastruttura di proiezione può essere utilizzato a livello di programmazione in primavera MVC controller. Basta dichiarare un bean Spring per SpelAwareProxyProjectionFactory:

@Configuration 
class SomeConfig { 

    @Bean 
    public SpelAwareProxyProjectionFactory projectionFactory() { 
    return new SpelAwareProxyProjectionFactory(); 
    } 
} 

Poi iniettarlo nel vostro controller e usarlo:

@Controller 
class SampleController { 

    private final ProjectionFactory projectionFactory; 

    @Autowired 
    public SampleController(ProjectionFactory projectionFactory) { 
    this.projectionFactory = projectionFactory; 
    } 

    @PreAuthorize(value = "hasRole('ROLE_ADMIN')") 
    @RequestMapping(value = "https://stackoverflow.com/users/employee") 
    public Page<?> listEmployees(Pageable pageable) { 

    return usersRepository.findEmployeeUsers(pageable).// 
     map(user -> projectionFactory.createProjection(Projection.class, user); 
    } 
} 

Guarda come a partire dalla versione più recente Page ha un metodo map(…) che può essere utilizzato per trasformare il contenuto della pagina al volo. Utilizziamo un lambda JDK 8 per fornire una fase di conversione utilizzando lo ProjectionFactory.

+0

Grazie, sembra un approccio decente! Sfortunatamente non riesco a provarlo perché sono bloccato con SpringBoot 1.2.2 (3) - non ha la versione GA di laters del progetto spring-data ... Mi rendo conto che si tratta di una domanda diversa - ma è c'è modo di mettere la GA in un'app di SpringBoot 1.2.2 o 1.2.3 per testare questa cosa? – Barbadoss

+1

Ecco come farlo - http://spring.io/blog/2015/03/26/what-s-new-in-spring-data-fowler, andando a provare e provare la nuova infrastruttura di proiezioni. – Barbadoss

+0

@OliverGierke sembra che questo non funzioni più nella versione corrente di Spring Data? Utilizzando l'esempio fornito, Jackson lancia un 'com.fasterxml.jackson.core.JsonGenerationException: Impossibile avviare un oggetto, aspettando il nome del campo' –

Problemi correlati