java 如何为@MappedSuperclass 实现 Spring Data 存储库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27545276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement a Spring Data repository for a @MappedSuperclass
提问by Xtreme Biker
I've got a JPA @MappedSuperClass
and an @Entity
extending it:
我有一个 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
}
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:
active
基类的字段是子实体的标志。应仅在应用程序中加载活动的。然后我编写了一个通用的Spring Data Proxy 接口:
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
And this one is the interface that should be for Worker
data access, properly extending the previous one:
而这个应该是Worker
数据访问的接口,适当的扩展上一个:
@Transactional
public interface WorkerDao extends Dao<Worker, Long>{}
Well, now in my logic layer I've implemented an abstract class which will wrap the common code for CRUDoperations 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:
好吧,现在在我的逻辑层中,我已经实现了一个抽象类,它将在我的实体上包装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
}
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:
问题在于该getDao()
方法使用E
class 参数,该参数保证仅是 的子项BaseClass
而不是javax.persistence.Entity
。当我尝试从自定义服务实现访问 DAO 时,出现此错误:
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)
引起:java.lang.IllegalArgumentException:无法为方法公共抽象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: Not an entity: class com.mycompany.model.BaseClass at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
Which makes sense, because E
is defined as a child of BaseClass
. The compiler allows me to write this too:
这是有道理的,因为E
被定义为BaseClass
. 编译器也允许我这样写:
public abstract class GenericService<E extends BaseClass && Entity>
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?
但是,我在子服务中收到错误消息,指出Worker
类与E
. 有谁知道如何解决这个问题?
回答by Xtreme Biker
It's just a matter of annotating the abstract Repository
as @NoRepositoryBean
:
这只是将摘要注释Repository
为@NoRepositoryBean
:
@NoRepositoryBean
public interface Dao<T extends BaseClass, E extends Serializable> extends
CrudRepository<T, E> {
Iterable<T> findByActive(Boolean active);
}
This way Spring relies on the underlying repository implementation to execute the findByActive
method.
这样 Spring 就依赖底层存储库实现来执行该findByActive
方法。
Regarding to the annotation type restriction issue, it's not possible to declare an annotation restricted type. See the referenced answers below.
关于注释类型限制问题,无法声明注释限制类型。请参阅下面的参考答案。
See also:
也可以看看: