0

我有以下实体:Quiz、Slide、TextSlide 和 SlideType。一个测验可以有多个不同类型的幻灯片,例如 TextSlide、QuestionSlide 等。为简洁起见,我仅在此示例中包含了 TextSlide。SlideType 表作为一种存储所有幻灯片类型(如枚举)的方式,但以适当的 SQL 方式,因此使用 INT id。表格如下所示:

CREATE TABLE QUIZ (
    id         INT AUTO_INCREMENT PRIMARY KEY,
    name       VARCHAR(255) NOT NULL,
    ...
);
CREATE TABLE SLIDE (
    id         INT AUTO_INCREMENT,
    `index`    INT NOT NULL,
    quiz_id    INT NOT NULL,
    ...
);
CREATE TABLE SLIDE_TEXT (
    slide_id INT          NOT NULL,
    text     VARCHAR(255) NOT NULL,
    CONSTRAINT SLIDE_TEXT_pk PRIMARY KEY (slide_id),
    CONSTRAINT SLIDE_TEXT_SLIDE_id_fk FOREIGN KEY (slide_id) REFERENCES SLIDE (id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE SLIDE_TYPE (
    id          INT AUTO_INCREMENT,
    code        VARCHAR(32)  NOT NULL,
    name        VARCHAR(64)  NOT NULL,
    description VARCHAR(128) NULL,
    CONSTRAINT SLIDE_TYPE_pk PRIMARY KEY (id)
);

这使得 Slide 成为一个有点抽象的类,只有三个常用参数:id、index 和 quiz_id。TextSlide 和 QuestionSlide 等实现都有不同的字段,但是从这个 Slide 实体扩展而来。

我将如何使用 JPA 在 Java 中解决这个问题,如下所示:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "SLIDE")
public abstract class Slide {
    @Id
    @GeneratedValue
    @Column
    private Integer id;

    // ...

    @OneToOne
    @JoinColumn(name = "slide_type_id")
    private SlideType slideType;

    public Slide(Integer id, /*...*/ SlideType slideType) {
        this.id = id;
        this.slideType = slideType;
    }
}

// PersistableEnum is an interface to help with conversion.
@Entity
@Table(name = "SLIDE_TYPE")
public enum SlideType implements PersistableEnum<SlideType, Integer> {
    TEXT(1),
    QUESTION(2);

    @Id
    @GeneratedValue
    @Column(name = "id")
    private final Integer id;

    SlideType(Integer id) {
        this.id = id;
    }

    @Override
    public Integer getId() {
        return id;
    }
}
@Entity
@PrimaryKeyJoinColumn(name = "slide_id")
@Table(name = "SLIDE_TEXT")
public final class TextSlide extends Slide {
    @Column(nullable = false, length = 255)
    private String text;

    // ...

    public TextSlide(Integer index, /*...*/ String text) {
        super(index, SlideType.TEXT);
        this.text = text;
    }
}

但是,我似乎想不出用 Mikro-ORM 做到这一点的解决方案。有几个挑战:

  • 枚举不能用作实体
  • 使用 TextSlide 扩展 Slide 会导致 TextSlide 继承 Slide 的属性,而我实际上希望 TextSlide 是 Slide 实体的实现,其中某些字段属于 Slide (id, index, quiz_id, ...) 并且某些字段属于 TextSlide (slide_id , 文本, ...); 我想使用一个通用超类(Slide)的原因是因为 Quiz 可以急切地获取所有实现,并且在我以后需要特定属性之前我不必担心类型。

有人可以指出我正确的方向吗?提前致谢。

4

0 回答 0