我有一个 JPA @MappedSuperClass
和一个扩展它的 @Entity
:
I've got a JPA @MappedSuperClass
and an @Entity
extending it:
@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 接口:
The active
field of the base class is a flag for the children entities. Only the active ones should be loaded in the application. Then I've written a generic Spring Data Proxy interface:
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
而这个应该是Worker
数据访问的接口,适当地扩展了上一个:
And this one is the interface that should be for Worker
data access, properly extending the previous one:
@Transactional
public interface WorkerDao extends Dao<Worker, Long>{}
好吧,现在在我的逻辑层中,我实现了一个抽象类,它将包装我的实体上 CRUD 操作的通用代码.我将为他们每个人提供服务,但我只想从 abstract
继承.我想为每个服务连接特定的存储库,并使用 abstract
方法将其提供给超类.这就是我的超类的实现方式:
Well, now in my logic layer I've implemented an abstract class which will wrap the common code for CRUD operations over my entities. I'll have a service for each of them, but I want just to inherit from the abstract
one. I want to wire the specific repository for each of the services and provide it to the superclass using an abstract
method. That's how my superclass is implemented:
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 时,我收到此错误:
The problem is that the getDao()
method uses the E
class parameter, which is guaranteed only to be a child of BaseClass
and not a javax.persistence.Entity
. When I try to access the DAO from my custom service implementation I get this error:
原因: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)
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)
原因:java.lang.IllegalArgumentException:不是实体:com.mycompany.model.BaseClass 类在 org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
Caused by: java.lang.IllegalArgumentException: Not an entity: class com.mycompany.model.BaseClass at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
这是有道理的,因为 E
被定义为 BaseClass
的子级.编译器也允许我这样写:
Which makes sense, because E
is defined as a child of BaseClass
. The compiler allows me to write this too:
public abstract class GenericService<E extends BaseClass && Entity>
但是,我在子服务中收到一个错误,提示 Worker
类与 E
的签名不兼容.有人知道怎么解决吗?
However I get an error in the child Service that says Worker
class is not compatible with the signature for E
. Does anybody know how to solve this?
只是将抽象的Repository
注释为@NoRepositoryBean
:
@NoRepositoryBean
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
这种方式 Spring 依赖于底层存储库实现来执行 findByActive
方法.
This way Spring relies on the underlying repository implementation to execute the findByActive
method.
关于注解类型限制问题,无法声明注解限制类型.请参阅下面的参考答案.
Regarding to the annotation type restriction issue, it's not possible to declare an annotation restricted type. See the referenced answers below.
另请参阅:
这篇关于如何为 @MappedSuperclass 实现 Spring Data 存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!