如何为@MappedSuperclass实现Spring Data存储库 [英] How to implement a Spring Data repository for a @MappedSuperclass
问题描述
我有一个JPA @MappedSuperClass
和一个 @Entity
扩展它:
@MappedSuperclass
public class BaseClass {
@Id
@ GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
私有布尔激活;
// getters& setters
}
@Entity
public class Worker extends BaseClass {
@Column
private String name;
// getters& setters
}
public interface Dao CrudRepository< T,E> {
Iterable< T> findByActive(布尔有效);
$ / code> 这是一个应该用于 Worker
数据访问,正确地扩展前一个:
@Transactional
public interface WorkerDao扩展Dao< Worker,Long> {}
,现在在我的逻辑层中,我已经实现了一个抽象类,它将通过我的实体包装 CRUD 操作的通用代码。我将为他们每个人提供服务,但我只想从摘要
一个继承。我想连接每个服务的特定存储库,并使用 abstract
方法将其提供给超类。这就是我的超类实现的方式:
public abstract class GenericService< E extends BaseClass> {
public abstract Dao< E,Long> getDao();
//这里我有一些常见的操作来管理
//所有的应用程序类,包括Worker
}
$ b 问题在于 getDao()
方法使用 E
类参数,它仅保证是 BaseClass
的子元素,而不是 javax.persistence.Entity
。当我尝试从我的自定义服务实现中访问DAO时,出现此错误:
引起的错误:java.lang.IllegalArgumentException:Could not为方法创建查询元模型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:不是实体:class com.mycompany.model.BaseClass
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
blockquote>
这是有道理的,因为 E
被定义为的子元素BaseClass
。编译器允许我写这个:
public abstract class GenericService< E extends BaseClass& &安培;实体GT;
然而,我在子Service中得到一个错误,表示 Worker
class与 E
的签名不兼容。是否有人知道如何解决这个问题?
解决方案 这只是注解摘要 Repository code>作为 @NoRepositoryBean
:
@NoRepositoryBean
public interface Dao< T extends BaseClass,E extends Serializable>延伸
CrudRepository< T,E> {
Iterable< T> findByActive(布尔有效);
$ b这样,Spring依靠底层的存储库实现来执行 findByActive
方法。
关于注解类型限制问题,不可能声明注解受限制输入即可。
另请参阅:
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
}
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);
}
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>{}
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
}
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:
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)
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>
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?
解决方案 It's just a matter of annotating the abstract Repository
as @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.
Regarding to the annotation type restriction issue, it's not possible to declare an annotation restricted type. See the referenced answers below.
See also:
- Generic Spring Data JPA repository implementation to load data by class type
- Annotations: restrict reference to classes with a annotation
这篇关于如何为@MappedSuperclass实现Spring Data存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!