如何为@MappedSuperclass实现Spring Data存储库 [英] How to implement a Spring Data repository for a @MappedSuperclass

查看:124
本文介绍了如何为@MappedSuperclass实现Spring Data存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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

}

active 字段是子实体的标志。只有活动的应该加载在应用程序中。然后我写了一个通用的 Spring Data Proxy接口

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:

这篇关于如何为@MappedSuperclass实现Spring Data存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆