我有以下实体: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 可以急切地获取所有实现,并且在我以后需要特定属性之前我不必担心类型。
有人可以指出我正确的方向吗?提前致谢。