(CRUD)大量JPA类的存储库

时间:2018-03-02 12:05:49

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

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

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

我可以通过

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

并且可以做这样的事情:

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

到目前为止没问题。

但我的问题是我有约。 500个JPA类,需要访问每个表,这意味着以上述方式定义500个存储库。

所以确实存在一种通过一些Spring Data&#34; magic&#34;动态创建的东西。从我的观点来看应该存在,否则以上是不可能的。它看起来像this is similar to my problem

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

您可以为500个类创建一个基本的抽象实体,然后为此类创建一个repo 。 (我认为通常的做法是为项目中的每个实体设置一个BaseEntityidversion等。

对于简单的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);