Spring Data Rest中同一实体的多个仓库

34

在Spring Data Rest中,是否可以为相同的JPA实体发布两个不同的存储库?我将这两个存储库分别命名为不同的路径和关系名称,但只有其中一个作为REST端点可用。我之所以拥有两个存储库,是因为其中一个是摘录,仅显示实体的基本字段。


3
这是不可能的。使用Spring Data REST,托管的资源是实体而不是存储库。该库维护一个托管资源的 Map,其中键是实体类。因此,实体只能同时映射到一个存储库接口(因为 Map 一次只能保存一个键的值)。如果您的应用程序需要每个实体类有多个存储库,您可能需要向Spring Data团队提出增强请求。 - manish
有MultiMaps。从技术上来说,肯定没有障碍。从语义角度来看,在我们的用例中,资源不能被识别为实体,而是视图,就像DB中的视图一样。视图对应于Spring Data Rest中的投影。因此,如果我可以将投影和对它们的操作映射到资源,那就太好了。 - Gregor
我的评论基于实际的Spring Data REST实现。我知道有像MultiMap这样的结构,所以我建议您考虑向Spring Data团队提出增强请求。 - manish
对于您的评论,对我来说,表和其视图是不同的对象。如果您必须执行DDL以触发DML查询,则变成了一个单独的对象。如果数据库将表和视图分开处理,则其他应用程序层也应该这样做。考虑到这一点,表将被映射到自己的JPA实体,而视图将映射到自己的单独实体。两者都可以拥有自己的存储库接口,并且现有的Spring Data REST基础设施将正常工作。 - manish
4个回答

20

糟糕的是,你每个实体只能有一个Spring Data Rest仓库(@RepositoryRestResource),而且如果你有一个常规的JPA @Repository(如CrudRepository或PagingAndSorting),它也将与Spring Data Rest进行交互(因为映射中的键是实体本身)。我浪费了不少时间来调试其中一个的随机加载。我想,如果这是Spring Data Rest的硬性限制,那么在尝试覆盖值时,如果映射的键已经存在,就应该抛出异常。


3
我已经为此创建了一个Jira Issue:https://jira.spring.io/browse/DATAREST-923,请随意投票支持! - Tim
示例用例:JPA存储+使用Elasticsearch repo进行搜索 - aux
@Tim:我们有类似的需求,需要两个不同的存储库(一个指向MySQL主实例,另一个指向只读访问从实例)。所有基于用户的交易都应与我们的主存储库交互。批处理框架(仅执行读取操作)应与从实例交互。 - Chinmay

4
答案似乎是:每个实体只有一个存储库可用。

4

我最终使用了@Subselect创建了第二个不可变实体,并将其绑定到第二个JpaRepository,并将其设置为@RestResource(exported = false),这也鼓励关注点的分离。

雇员示例

@Entity
@Table(name = "employee")
public class Employee {

    @Id
    Long id

    String name

    ...

}

@RestResource
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {

}

@Entity
@Immutable   
@Subselect(value = 'select id, name, salary from employee')
public class VEmployeeSummary {

    @Id
    Long id

    ...

}

@RestResource(exported = false)
public interface VEmployeeRepository extends JpaRepository<VEmployeeSummary, Long> {

}

背景

在单体应用程序中,有两个包具有不同的要求。一个需要在PagingAndSortingRepository中公开实体,包括CRUD函数,以便UI使用。另一个用于聚合后端报告组件,没有分页但具有排序功能。

我知道我可以在请求Pageable.unpaged()之后从PagingAndSorting Repository中过滤结果,但我只想要一个基本的返回List的JPA存储库,用于某些过滤器。


1

因此,这并没有直接回答问题,但可能有助于解决潜在的问题。

每个实体只能有一个存储库...但是,您可以在一个表中拥有多个实体;因此,在一个表中可以有多个存储库。

在我编写的一段代码中,我不得不创建两个实体...一个带有自动生成的ID,另一个带有预设的ID,但两者都指向同一张表:

@Entity
@Table("line_item")
public class LineItemWithAutoId {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;

    ...
}



@Entity
@Table("line_item")
public class LineItemWithPredefinedId {

    @Id
    private String id;

    ...
}

然后,我为每个项目建立了一个代码库:
public interface LineItemWithoutId extends Repository<LineItemWithAutoId,String> {

    ...

}


public interface LineItemWithId extends Repository<LineItemWithPredefinedId,String> {

    ...

}

对于发布的问题,您可以有两个实体。一个是完整的实体,具有所有属性的getter和setter。另一个实体只有针对您想公开的字段的getter,但是有所有属性的setter。这有意义吗?


我尝试了这个,但是Hibernate似乎对此不满意:org.hibernate.tool.schema.spi.SchemaManagementException: SQL字符串已经添加了多次:line_item - Cyril Gambis

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