理解Spring数据中的存储库

理解Spring数据中的存储库,spring,spring-data,spring-data-jpa,Spring,Spring Data,Spring Data Jpa,我想创建一个“通用”存储库,用于查询来自多个实体的数据。如果我这样做: @Repository public interface MyRepository { @Query("select r from Role r") List<Role> getRoles(); } @存储库 公共接口MyRepository{ @查询(“从角色r中选择r”) 列出getRoles(); } 我得到一个错误,因为当需要MyRepository实例时,Spring没有找到要注

我想创建一个“通用”存储库,用于查询来自多个实体的数据。如果我这样做:

@Repository
public interface MyRepository {

    @Query("select r from Role r")
    List<Role> getRoles();

}
@存储库
公共接口MyRepository{
@查询(“从角色r中选择r”)
列出getRoles();
}
我得到一个错误,因为当需要MyRepository实例时,Spring没有找到要注入的实现。到目前为止,一切顺利。现在,如果我这样做:

@Repository
public interface MyRepository extends JpaRepository {

    @Query("select r from Role r")
    List<Role> getRoles();

}
@Repository
public interface MyRepository extends JpaRepository<User, String> {

    @Query("select r from Role r")
    List<Role> getRoles();

} 
@存储库
公共接口MyRepository扩展了JpaRepository{
@查询(“从角色r中选择r”)
列出getRoles();
}
我得到一个错误,因为对象不是JPA托管类型(JpaRepository是泛型的)。好的,再说一遍。如果我这样做:

@Repository
public interface MyRepository extends JpaRepository {

    @Query("select r from Role r")
    List<Role> getRoles();

}
@Repository
public interface MyRepository extends JpaRepository<User, String> {

    @Query("select r from Role r")
    List<Role> getRoles();

} 
@存储库
公共接口MyRepository扩展了JpaRepository{
@查询(“从角色r中选择r”)
列出getRoles();
} 

它起作用了。为什么?我为实体用户而不是角色声明JpaRepository。为什么JpaRepository需要一个具体的实体,即使查询是针对另一个实体的?

Spring Data中的每个存储库都必须扩展存储库接口,即通用接口,因此,您必须始终指定要使用的实体,而您对此无能为力,因为这是Spring数据的实现方式。您可以在此处找到有关创建存储库的更多信息:

另一方面,您当然可以向存储库指定一个实体,然后添加返回其他类型实体的方法,因为在您的界面中,您可以添加任何您想要的内容(还要注意,存储库界面没有方法)。但是,如果要使用父接口的方法,则必须使用指定的实体


在您的示例中,您可以按照@M.Deinum的建议执行,创建一个
JpaRepository
,并使用
findAll
查询,这样做更有意义。使用
JpaRepository
只是对框架的滥用。

因为它还定义了其他方法,如
findAll
findOne
等。在这种情况下,这些方法只适用于
User
。当您指定了一个带有
@Query
的方法时,它会查看方法签名。即使我只想使用@Query进行查询,我也必须扩展JpaRepository吗?为什么您甚至需要对此进行查询?只需创建一个
RoleRepository扩展了JpaRepository
,并使用
findAll
方法。但从理论上讲,您可以扩展
Repository
而不是
JpaRepository
,但是为什么要使用Spring数据JPA呢?你失去了所有的好处。我只是想避免拥有30个不同的
{Entity}存储库。将它们全部放在一个界面中会很好。