如何为@MappedSuperclass实现一个Spring Data仓库

35

我有一个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代理接口

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操作的通用代码。我将为每个服务创建一个服务,但我只想继承抽象类。我想要为每个服务连接特定的存储库,并使用抽象方法将其提供给超类。以下是我的超类实现:

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时,会出现以下错误:

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)

这很有道理,因为E被定义为BaseClass的子类。编译器也允许我编写以下内容:
public abstract class GenericService<E extends BaseClass && Entity>

然而,我在子服务中遇到了一个错误,它说Worker类与E的签名不兼容。有人知道如何解决这个问题吗?


不是,它应该是具体管理器指定的类型,即Worker - cy3er
@cy3er没错,它一定是BaseClass的子类。然而,JPA正在寻找一个@Entity,而BaseClass只是一个@MappedSuperclass - Aritz
这个类似的问题已经解决了我的问题。关键在于将抽象存储库注释为“@NoRepositoryBean”。这篇文章解决了我所问的问题,即不可能有一个受注释限制的类型。 - Aritz
1个回答

51

将抽象的Repository注释为@NoRepositoryBean即可:

@NoRepositoryBean
public interface Dao<T extends BaseClass, E extends Serializable> extends
        CrudRepository<T, E> {

    Iterable<T> findByActive(Boolean active);

}

这种方式中,Spring依赖底层存储库实现来执行findByActive方法。
关于注释类型限制问题,不可能声明一个注释受限类型。请参见下面引用的答案。 另请参阅:

那个注解是我实现中唯一缺失的部分,你刚刚帮我解决了一个长时间令人尴尬的头痛问题:D... 谢谢! - Shessuky
你真是个英雄。谢谢。我一直在想这个。 - OctavioCega

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接