Spring Data(JPA)多个存储库而不需要多个类

4
在我的当前项目中,我正在使用Spring Data JPA,并且我有超过20个@Entity类。我想为它们创建存储库,但是为它们创建另一个带@Repository注释的模型类似乎有点过头了,而且会有很多“重复”的代码 - 所有存储库类看起来都像:
@Repository
public interface SomeModelRepository extends CrudRepository<SomeModel, Long> {
}

有没有一种方法可以“自动化”创建这些存储库?并且只指定那些我将使用自己的方法扩展的存储库?在DRY和KISS的原则下,应该如何处理这些问题?

2
不需要...你需要接口。而且你不需要@Repository,它没有任何作用。 - M. Deinum
1
一旦您的项目扩大并且需要为一个或多个实体添加额外的查询时,您会很高兴拥有为每个实体定义的单独接口。 - marco.eig
3
除此之外,你真的需要为每个实体都创建一个仓库吗?通常,一些实体是所有者/聚合根,其余实体只是它们的子项,不会直接查询。 - Adam Michalik
好的,谢谢回复。如果每个实体都需要一个仓库,我会重新考虑并只创建真正需要的。 - elwin013
3个回答

3
如上面的评论所提到的(在问题中) - 不需要,我必须为我需要的每个实体创建存储库。此外,值得考虑的是聚合根(如果一些实体不会直接查询)。

2
当我使用大约100多个实体的数据源时,我使用了以下方法,以便不为每个实体创建存储库。我主要用于仅将信息从源保存到我们的数据库中。但是也有一些关于如何检索数据的想法。
创建@MappedSuperclass的主要思想: "最初的回答"
@MappedSuperclass
public abstract class SuperClass {

    @Id
    @GeneratedValue
    private Integer id;

    public SuperClass() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

然后扩展所有其他实体:

最初的回答

@Entity
public class Class1 extends SuperClass {

    private String classInfo;

    public String getClassInfo() {
        return classInfo;
    }

    public void setClassInfo(String classInfo) {
        this.classInfo = classInfo;
    }

    @Override
    public String toString() {
        return "\nClass1{" +
                "classInfo='" + classInfo + '\'' +
                '}';
    }
}

@Entity
public class Class2 extends SuperClass {

    private String classInfo;

    public String getClassInfo() {
        return classInfo;
    }

    public void setClassInfo(String classInfo) {
        this.classInfo = classInfo;
    }

    @Override
    public String toString() {
        return "\nClass2{" +
                "classInfo='" + classInfo + '\'' +
                '}';
    }
}

在这种情况下,您的代码库将是:

public interface SuperRepository extends JpaRepository<SuperClass, Integer> {

}

"最初的回答":并且您可以应用它:

    Class1 class1 = new Class1();
    class1.setClassInfo("Class1 info");

    Class2 class2 = new Class2();
    class2.setClassInfo("Class2 info");

    superRepository.save(class1);
    superRepository.save(class2);

    //OR 
    //List<SuperClass> entities = Arrays.asList(class1,class2);
    //superRepository.saveAll(entities);

Hibernate将创建Class1Class2表,并填充它们的数据。
下一步是如何检索数据。 我建议这样的方法-在这个存储库中为每个类创建查询:
public interface SuperRepository extends JpaRepository<SuperClass, Integer> {

    @Query("select c from Class1 c")
    List<Class1> findAllClass1();

    @Query("select c from Class2 c")
    List<Class2> findAllClass2();

}

Then when you apply this:

    System.out.println(superRepository.findAllClass1());
    System.out.println(superRepository.findAllClass2());

你将会得到:

[类1{类信息='类1信息'}]

[类2{类信息='类2信息'}]

注:Original Answer翻译成"最初的回答",但是在提供的内容中并没有这个词汇。

1
我没有点赞,因为它并没有按照问题所要求的方式回答。但是我真的很喜欢你提出的方法。我会使用它的。 - Shashikant Soni

0

对于那些想要避免太多存储库接口文件的人,Spring 5.0 中有一种称为“可组合存储库”的东西,并且有相当多的示例代码可用,因此我不会在这里重新解释。我发现了一种类似的方法来避免太多的文件:

创建一个普通类,它成为所有这些空存储库接口的供应商。在包含类中定义 @Repository 接口作为非公共接口,并为每个存储库编写 getter。以下是示例:

Public MyRepositoryProvider {

  @Autowired 
  Class1Repository class1Repo;
  public Class1Repository getClass1Repo() {
      return class1Repo;

  //.... similarly for Class2Repo

}

@Repository
interface Class1Repository extends CRUDRepository<Class1, Long>{}
@Repository
interface Class2Repository extends CRUDRepository<Class2, Long>{}

把所有这些内容放在一个Java文件中。并确保其在存储库扫描您的项目的路径中。

我认为这并不起作用,因为接口没有在额外的文件中定义,因此也不是公共的。但你可以在另一个文件中创建一个超类,比如说 NestedRepository,所有嵌套存储库都继承它(而不是 CrudRepository)。然后,RepositoryProvider 的成员必须是 NestedRepository 类型。由于超级接口在自己的文件中定义,所以它具有公共可见性。 - Melkor

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