【问题标题】:(CRUD) Repository for a large number of JPA classes(CRUD) 大量 JPA 类的存储库
【发布时间】:2018-08-10 15:35:13
【问题描述】:

我可以通过在适当的 JPA 类 A 上定义一个接口来创建一个存储库,如下所示:

public interface ARepository extends CrudRepository<A, Long>
{
}

我可以通过

在我的控制器中使用它(例如)
@Autowired
private ARepository aRepository;

并且可以做这样的事情:

aRepository.save(..);
aRepository.findAll();
..

目前没有问题。

但我的问题是我有 ca。 500 个 JPA 类,需要访问每个表,这意味着以上述样式定义 500 个 Repositories。

确实存在通过一些 Spring Data “魔法”动态创建的东西,从我的角度来看,它应该存在,否则上述内容将是不可能的。看起来像this is similar to my problem

除了与上述相关的另一个问题。我可以在界面中定义findBy... 方法,并且在后台会为这个特定属性生成一个查询方法。问题还在于这是否可以以与上一个问题相关的动态方式完成,因为我有一组需要补充查询方法的表..

【问题讨论】:

    标签: java spring-boot spring-data-jpa


    【解决方案1】:

    spring-data-generator可以自动为你生成接口。

    关于你的第二个问题,我认为你不能以动态的方式完成。 Java 是静态编译的,无法动态添加成员。可能有一个工具可以为这些方法生成代码,但如果该工具为所有列组合生成方法,您最终会得到大量方法。

    【讨论】:

    • 首先感谢您的回答,但生成存储库可以在 10-15 分钟内轻松完成..也许我不够清楚我不想生成我会手动编写的代码.我想到了一些更通用的东西......
    【解决方案2】:

    您可以为您的 500 个类创建一个基本 abstract 实体,然后为该类创建 一个 repo。 (我认为对于项目中的每个实体,有一个带有idversion 等的BaseEntity 类是一种常见的做法)。

    对于简单的 repo 方法(如 savefindAll 等),它可以直接使用(注意 - 实体必须具有相同的 id 类型)。例如:

    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstarct class BaseEntity {
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE)
        private Long id;
    }
    
    @Entity
    public class Entity1 extends BaseEntity {
        private String name;
    }
    
    @Entity
    public class Entity2 extends BaseEntity {
        private String name;
    }
    
    public interface BaseEntityRepo extends JpaRepository<BaseEntity, Long> {
    }
    

    注意BaseEntity 必须有@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 以防止对每个实体使用单表base_entity。并且它们的id 不能相交(参见@GeneratedValue(strategy = GenerationType.SEQUENCE))。

    用法:

    @RunWith(SpringRunner.class)
    @SpringBootTest    
    public class BaseEntityRepoTest {
    
        @Autowired private BaseEntityRepo repo;
    
        @Before
        public void setUp() throws Exception {    
            repo.save(asList(
                    new Entity1("entity1"),
                    new Entity2("entity2")
            ));
        }
    
        @Test
        public void readingTest() throws Exception {
            List<BaseEntity> entities = repo.findAll();
            assertThat(entities).hasSize(2);
        }
    }
    

    关于你的第二个问题,你可以使用这种方法:

    public interface BaseEntityRepo extends JpaRepository<BaseEntity, Long> {
        <T> T findById(Long id, Class<T> type);
    }
    

    用法:

    @Test
    public void findById() {
        final Entity1 entity1 = repo.findById(1L, Entity1.class);
        final Entity2 entity2 = repo.findById(2L, Entity2.class);
        assertThat(entity1).isNotNull();
        assertThat(entity2).isNotNull();
    }
    

    但是您只能为基类中存在的继承实体的“公共”属性构建 repo 查询方法。要使此方法起作用,您必须将 name 参数移动到 BaseEntity

    <T> List<T> findAllByNameLike(String name, Class<T> type);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      • 2021-04-06
      • 1970-01-01
      相关资源
      最近更新 更多