【问题标题】:How to implement a Spring Data repository for a @MappedSuperclass如何为 @MappedSuperclass 实现 Spring Data 存储库
【发布时间】:2015-02-17 03:55:15
【问题描述】:

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

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 操作的通用代码。我将为他们每个人提供服务,但我只想从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

}

问题在于getDao() 方法使用E 类参数,该参数只能保证是BaseClass 的子代,而不是javax.persistence.Entity。当我尝试从我的自定义服务实现访问 DAO 时,我收到此错误:

原因: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)

原因:java.lang.IllegalArgumentException:不是实体:com.mycompany.model.BaseClass 类 在 org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)

这是有道理的,因为E 被定义为BaseClass 的子级。编译器也允许我这样写:

public abstract class GenericService<E extends BaseClass && Entity>

但是,我在子服务中收到错误消息,指出 Worker 类与 E 的签名不兼容。有人知道怎么解决吗?

【问题讨论】:

  • 只保证是BaseClass不,应该是具体管理器指定的类型,本例中为Worker
  • @cy3er 正确。它保证是BaseClass 的孩子。但是,JPA 正在寻找 @Entity,而 BaseClass 只是 @MappedSuperclass
  • This similar question 解决了我的问题。这是将抽象存储库注释为@NoRepositoryBean 的问题。这个post 解决了我的要求,注释限制类型是不可能的。

标签: java generics jpa spring-data


【解决方案1】:

只需将摘要Repository 注释为@NoRepositoryBean

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

    Iterable<T> findByActive(Boolean active);

}

这种方式 Spring 依赖于底层存储库实现来执行findByActive 方法。

关于注解类型限制问题,无法声明注解限制类型。请参阅下面的参考答案。

另请参阅:

【讨论】:

  • 该注释是我的实现中唯一缺少的部分,在长时间令人尴尬的头痛之后,你刚刚救了我:D...谢谢你!
  • Ypu 人,是个英雄。谢谢。错过了这个。
猜你喜欢
  • 2015-07-10
  • 2016-12-30
  • 2016-11-25
  • 2016-07-04
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
相关资源
最近更新 更多