2014-12-18 5 views
12

Ho un JPA @MappedSuperClass e un @Entity estendendola:Come implementare un repository primavera dati per un @MappedSuperclass

@MappedSuperclass 
public class BaseClass { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @Column 
    private Boolean active; 

    //getters & setters 

} 

@Entity 
public class Worker extends BaseClass{ 

    @Column 
    private String name; 

    //getters & setters 

} 

La active campo della classe di base è una bandiera per le entità bambini. Nell'applicazione devono essere caricati solo quelli attivi. Poi ho scritto un generico Spring Data Proxy interface:

public interface Dao<T extends BaseClass, E extends Serializable> extends 
     CrudRepository<T, E> { 

    Iterable<T> findByActive(Boolean active); 

} 

e questo è l'interfaccia che dovrebbe essere per Worker accesso ai dati, che si estende correttamente alla precedente:

@Transactional 
public interface WorkerDao extends Dao<Worker, Long>{} 

Bene, ora nel mio livello di logica Ho implementato una classe astratta che avvolgerà il codice comune per le operazioni CRUD sulle mie entità. Avrò un servizio per ognuno di loro, ma voglio ereditare solo da quello abstract. Voglio collegare il repository specifico per ciascuno dei servizi e fornirlo alla superclasse usando un metodo abstract. Ecco come il mio superclasse è implementato:

public abstract class GenericService<E extends BaseClass>{ 

    public abstract Dao<E, Long> getDao(); 

    //Here I've got some common operations for managing 
    //all my application classes, including Worker 

} 

Il problema è che il metodo getDao() utilizza il parametro E di classe, che è garantito solo per essere un figlio di BaseClass e non un javax.persistence.Entity. Quando provo ad accedere al DAO dalla mia implementazione del servizio personalizzato ottengo questo errore:

Caused by: java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract java.lang.Iterable com.mycompany.model.daos.interfaces.Dao.findByActive(java.lang.Boolean)! at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:93)

Caused by: java.lang.IllegalArgumentException: Not an entity: class com.mycompany.model.BaseClass at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)

che ha un senso, perché E è definito come un bambino di BaseClass. Il compilatore mi permette di scrivere anche questo:

public abstract class GenericService<E extends BaseClass && Entity> 

Tuttavia ottengo un errore nel servizio del bambino che dice Worker classe non è compatibile con la firma per E. Qualcuno sa come risolvere questo?

+0

* che è garantito solo per essere un BaseClass * No, dovrebbe essere il tipo che specifica gestore concreti, in questo caso 'Lavoratore'. – cy3er

+0

@ cy3er corretto. È garantito che sia figlio di 'BaseClass'. Tuttavia, JPA sta cercando un '@ Entity' e' BaseClass' è un semplice '@ MappedSuperclass'. –

+0

[Questa domanda simile] (http: // StackOverflow.it/questions/21415551/generico-spring-data-jpa-repository-implementation-to-load-data-by-class-type) ha risolto il mio problema. Si trattava di annotare il repository astratto come '@ NoRepositoryBean'. Questo [post] (http://stackoverflow.com/a/11012490/1199132) risolve ciò che stavo chiedendo, un tipo con annotazione ristretta non è possibile. –

risposta

14

E 'solo una questione di annotare l'astratto Repository come @NoRepositoryBean:

@NoRepositoryBean 
public interface Dao<T extends BaseClass, E extends Serializable> extends 
     CrudRepository<T, E> { 

    Iterable<T> findByActive(Boolean active); 

} 

questo modo Primavera si basa sull'attuazione repository sottostante per eseguire il metodo findByActive.

Per quanto riguarda il problema di restrizione del tipo di annotazione, non è possibile dichiarare un tipo con annotazione limitata. Vedi le risposte di riferimento di seguito.

Consulta anche: