使用 Spring Boot JPA 映射星型模式

Posted

技术标签:

【中文标题】使用 Spring Boot JPA 映射星型模式【英文标题】:Mapping a Star Schema with Spring Boot JPA 【发布时间】:2020-11-23 15:21:48 【问题描述】:

我正在努力确定正确的注释,以。

让我们考虑 3 个表:

DIM_One (1)--------(1..n) FACT (1..n) ------------ (1) DIM_Two

DIM_One 和 DIM_Two 都有一个 id 作为它们的主键。 FACT的主键是(DIM_One_pk, DIM_Two_pk)的组合

目前,我的 DIM 表中的注释类似于:

@Table(name="DIM_One")
@Entity
@Getter
@ToString
public class One 

    @Id
    @Column(name = "dim_one_id")
    private UUID id;

    //...

至于 FACT 表,我有:

@Entity
@Table(name = "FACT")
@ToString
@Getter
public class Fact 
    @EmbeddedId
    private FactId id;

    //...


具有相应的 FactId 类:

@Embeddable
@Getter
@EqualsAndHashCode
public class FactId implements Serializable 
    private One one;
    private Two two;

我觉得我需要使用正确的注释来使其与基数相对应有点迷失:

DIM_One (1)--------(1..n) FACT (1..n) ------------ (1) Dim_Two

此外,它实际上应该映射为 OneToMany 还是 OneToOne ?

【问题讨论】:

【参考方案1】:

您的图表显示了 (1..n)---(1) 关系,因此应该像这样映射。

除此之外,您需要考虑如何使用它:

如果加载事实,是否要加载关联的维度条目?这会导致在急切加载和延迟加载之间做出决定。 您希望能够从事实导航到维度还是相反?或两者?这会导致有关方向性的决定。 如果你坚持,删除......一个事实维度应该加入该操作吗? => 级联配置。

注意:虽然原则上这应该没有大问题,但由于星型模式仍然只是一堆表,这听起来是一个非常糟糕的主意。

星型模式用于大量数据,并且高度非规范化以优化读取和聚合。 这意味着更新通常会从几百行到数千行,甚至可能是数百万行。 JPA 不是为这种操作而构建的,与专门定制的 SQL 语句相比,它的性能会很糟糕。

在阅读方面,您将不断地使用聚合函数以及可能带有非平凡表达式的窗口函数。 JPQL,JPA 的查询语言又不是为此而构建的,它将严重限制您的选择。

【讨论】:

感谢您富有洞察力的回答。您知道任何框架更适合此类任务吗? 我不知道任何特定的框架,但您正在寻找的术语是 ETL(提取转换负载),它是用于从各种来源提取数据、将它们转换(转换为星型模式)和将它们加载到各种数据库中。

以上是关于使用 Spring Boot JPA 映射星型模式的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot2 系列教程 | 使用 Spring Data JPA 访问 Mysql

JPA Spring Boot 微服务 - 使用两个多对一映射持久化实体时的无限循环

Spring Boot JPA @JoinTable 与现有映射表忽略 @GeneratedValue

Spring boot JPA - 延迟加载不适用于一对一映射

在 Spring Boot JPA 中映射枚举和时间类型

在 Spring Boot jpa 中将多个外键映射到同一个主键