【发布时间】:2015-02-17 03:55:15
【问题描述】:
我有一个 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:不是实体: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 的签名不兼容。有人知道怎么解决吗?
【问题讨论】:
-
只保证是BaseClass不,应该是具体管理器指定的类型,本例中为
Worker。 -
@cy3er 正确。它保证是
BaseClass的孩子。但是,JPA 正在寻找@Entity,而BaseClass只是@MappedSuperclass。 -
This similar question 解决了我的问题。这是将抽象存储库注释为
@NoRepositoryBean的问题。这个post 解决了我的要求,注释限制类型是不可能的。
标签: java generics jpa spring-data