2014-12-18 20 views
12

Mam WZP @MappedSuperClass oraz @Entity rozciągający go:Jak wdrożyć repozytorium Wiosna danych dla @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 

} 

active pole klasy bazowej jest flaga dla podmiotów dzieci. Tylko te aktywne powinny być załadowane do aplikacji. Wtedy pisałem ogólny Spring Data Proxy interface:

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

    Iterable<T> findByActive(Boolean active); 

} 

i ten jest interfejs, który powinien być dla Worker dostępu do danych, właściwie rozszerzenie poprzedniej:

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

Cóż, teraz w moim warstwy logiki Zaimplementowałem klasę abstrakcyjną, która będzie owijała wspólny kod dla operacji CRUD nad moimi elementami. Będę miał usługę dla każdego z nich, ale chcę tylko dziedziczyć po abstract. Chcę połączyć konkretne repozytorium dla każdej usługi i przekazać ją nadklasie przy użyciu metody abstract. To jak moja nadklasą jest realizowany:

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 

} 

Problemem jest to, że metoda getDao() używa parametru E klasy, który jest gwarantowany tylko być dzieckiem BaseClass a nie javax.persistence.Entity. Gdy próbuję otworzyć DAO z mojego realizacji niestandardowych usług otrzymuję ten błąd:

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)

co ma sens, ponieważ E jest zdefiniowany jako dziecko BaseClass. Kompilator pozwala mi napisać to zbyt:

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

Jednakże pojawia się błąd w Serwisie dziecko, które mówi Worker klasa nie jest zgodny z podpisem na E. Czy ktoś wie, jak rozwiązać ten problem?

+0

*, która jest zagwarantowana tylko być klasy bazowej * Nie powinno być typem, który konkretne określa kierownik w tym sprawa "Pracownik". – cy3er

+0

@ cy3er correct. To gwarantuje, że jest dzieckiem "BaseClass". Jednak JPA szuka '@ Entity', a' BaseClass' jest zwykłą '@ MappedSuperclass'. –

+0

[To podobne pytanie] (http: // stackoverflow.com/questions/21415551/generic-spring-data-jpa-repository-implementation-to-load-data-by-class-type) rozwiązało mój problem. Chodziło o opisanie abstrakcyjnego repozytorium jako '@ NoRepositoryBean'. Ten [post] (http://stackoverflow.com/a/11012490/1199132) rozwiązuje to, o co prosiłem, typ o ograniczonej adnotacji nie jest możliwy. –

Odpowiedz

14

To tylko kwestia opisywania streszczenie Repository jak @NoRepositoryBean:

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

    Iterable<T> findByActive(Boolean active); 

} 

ten sposób Wiosna opiera się na podstawowej implementacji repozytorium do realizacji metody findByActive.

W przypadku problemu z ograniczeniem opisu adnotacji, , nie można zadeklarować typu z ograniczoną adnotacją:. Zobacz odpowiedzi przywoływane poniżej.

Zobacz także: