У меня есть JPA @MappedSuperClass
и @Entity
, расширяющие его:
@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
базового класса является флагом для дочерних объектов. В приложение должны быть загружены только активные. Затем я написал общий Spring интерфейс Data Proxy:
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
И это один из интерфейсов, который должен быть для доступа к данным Worker
, правильно расширив предыдущий:
@Transactional
public interface WorkerDao extends Dao<Worker, Long>{}
Итак, теперь в моем логическом слое я реализовал абстрактный класс, который обернет общий код для операций CRUD над моими сущностями. У меня будет служба для каждого из них, но я хочу просто наследовать от abstract
. Я хочу связать конкретный репозиторий для каждой из сервисов и предоставить его суперклассу с помощью метода abstract
. То, как реализуется мой суперкласс:
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
}
Проблема заключается в том, что метод getDao()
использует параметр класса E
, который гарантированно будет только дочерним элементом BaseClass
, а не javax.persistence.Entity
. Когда я пытаюсь получить доступ к DAO из моей собственной реализации службы, я получаю эту ошибку:
Вызвано: java.lang.IllegalArgumentException: не удалось создать метамодель запроса для метода public abstract java.lang.Iterable com.mycompany.model.daos.interfaces.Dao.findByActive(java.lang.Boolean)! на org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy $CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:93)
Причиняет: java.lang.IllegalArgumentException: не объект: класс com.mycompany.model.BaseClass at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
Это имеет смысл, потому что E
определяется как дочерний элемент BaseClass
. Компилятор также позволяет мне написать это:
public abstract class GenericService<E extends BaseClass && Entity>
Однако я получаю сообщение об ошибке в дочерней службе, которая говорит, что класс Worker
не совместим с сигнатурой для E
. Кто-нибудь знает, как это решить?