我有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 interface:
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:不是实体:class com.mycompany.model.BaseClass 在org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
这是有道理的,因为E
被定义为BaseClass
的孩子。编译器允许我写这个:
public abstract class GenericService<E extends BaseClass && Entity>
但是,我在子服务中收到错误,指出Worker
类与E
的签名不兼容。有人知道如何解决这个问题吗?
答案 0 :(得分:20)
只需将摘要Repository
注释为@NoRepositoryBean
:
@NoRepositoryBean
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
这样,Spring依赖底层存储库实现来执行findByActive
方法。
关于注释类型限制问题,无法声明注释限制类型。请参阅下面的参考答案。
另见: