上下文
我有一个类Oeuvre
,还有两个子类Livre
和Magasine
。 Auteur
链接到Livre
。
所以类图看起来像:
Oeuvre
|
____________
| |
Magasine Livre____Auteur
实体
@Entity
public class Oeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idoeuvre;
@NotNull
private String titre;
@NotNull
private String ISBN;
@ColumnDefault("CURRENT_DATE()")
private LocalDate parution;
}
@Entity
public class Magasine extends Oeuvre {
@Enumerated(EnumType.STRING)
private Type type;
}
@Entity
public class Livre extends Oeuvre {
@ManyToOne
@JoinColumn(name = "idauteur")
private Auteur auteur;
}
@Entity
public class Auteur {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idauteur;
@NotNull
private String nom;
@NotNull
private String prenom;
}
H2表示形式
Oeuvre(idoeuvre, isbn, parution, titre, type, idauteur)
但是用这种表示形式,我可以有空值。例如,如果idauteur
是null
,则Oeuvre
将是Magasine
。
那么,这种表示方法更好吗?
Oeuvre(idoeuvre, isbn, parution, titre)
Livre(idlivre, idauteur, idoeuvre)
Magasine(idmagasine, type, idoeuvre)
SQL脚本
使用当前的数据库方案,我无法创建此约束:ALTER TABLE livre ADD FOREIGN KEY (idauteur) REFERENCES auteur(idauteur) ON UPDATE CASCADE
结论
是否可以用JPA / H2表示它?
感谢您的回答。
修改1:问题
是否可以在JPA / H2中使用这种数据库方案?
Oeuvre(idoeuvre, isbn, parution, titre)
Livre(idlivre, idauteur, idoeuvre)
Magasine(idmagasine, type, idoeuvre)
答案 0 :(得分:1)
您描述实体的方式,Hibernate将期望以下数据库结构:
oeuvre(idoeuvre, titre, isbn, parution)
magasine(idoeuvre, titre, isbn, parution, type)
livre(idoeuvre, titre, isbn, parution, idauteur)
这将导致很多重复,并且可能不是您想要的。现在,您确实描述了两种可能的解决方案,即:
定义一个名为oeuvre
的表,其中存在每个字段,例如:
oeuvre(idoeuvre, titre, isbn, parution, type, idauteur)
为livre
和magasine
定义单独的表,例如:
oeuvre(idoeuvre, titre, isbn, parution)
magasine(idmagasine, idoeuvre, idauteur)
livre(idlivre, idoeuvre, idauteur)
现在,正如您提到的那样,第一个解决方案不允许您定义约束,而第二个解决方案可以。基本上,这意味着您可以提供自己的答案,如果需要约束,则必须区分不同的类型,然后必须采用第二种方法。
然后您可以定义以下约束:
magasine.idoeuvre
和livre.idoeuvre
中的每一个都应该是唯一的(您甚至可以将它们用作主键)livre.idauteur
应该是not null
但是,在这种情况下,您不需要任何继承。通常,只有在多个表具有相同的字段的情况下,才能在Hibernate中进行继承,而在这种情况下,您将拥有三个单独的表,因此也有了三个单独的实体,不涉及继承:
@Entity
public class Oeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idoeuvre;
@NotNull
private String titre;
@NotNull
private String ISBN;
@ColumnDefault("CURRENT_DATE()")
private LocalDate parution;
}
@Entity
public class Magasine { // No extends
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idmagasine;
@OneToOne
@JoinColumn(name = "idoeuvre")
private Oeuvre oeuvre;
@Enumerated(EnumType.STRING)
private Type type;
}
@Entity
public class Livre { // No extends
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idlivre;
@OneToOne
@JoinColumn(name = "idoeuvre")
private Oeuvre oeuvre;
@ManyToOne
@JoinColumn(name = "idauteur")
private Auteur auteur;
}
在这种情况下可以使用继承的唯一原因是因为Magasine
和Livre
都具有相似的Oeuvre
映射,在这种情况下,您可以像这样更改代码:
@Entity
public class Oeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idoeuvre;
@NotNull
private String titre;
@NotNull
private String ISBN;
@ColumnDefault("CURRENT_DATE()")
private LocalDate parution;
}
@MappedSuperclass // No @Entity
public class SpecificOeuvre {
@OneToOne
@JoinColumn(name = "idoeuvre")
private Oeuvre oeuvre;
}
@Entity
public class Magasine extends SpecificOeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idmagasine;
@Enumerated(EnumType.STRING)
private Type type;
}
@Entity
public class Livre extends SpecificOeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idlivre;
@ManyToOne
@JoinColumn(name = "idauteur")
private Auteur auteur;
}
两者都代表相同的数据库结构,唯一的区别是它们中的一个具有单独的类,并用@MappedSuperclass
注释,其中包含Magasine
和Livre
之间的所有可重用信息,在这种情况下,仅是到Oeuvre
的映射。
如果您想知道Oeuvre
是链接到Livre
还是Magasine
,则可以使用双向映射,例如:
@Entity
public class Oeuvre {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String idoeuvre;
@NotNull
private String titre;
@NotNull
private String ISBN;
@ColumnDefault("CURRENT_DATE()")
private LocalDate parution;
@OneToOne(mappedBy = "oeuvre")
private Livre livre;
@OneToOne(mappedBy = "oeuvre")
private Magasine magasine;
}
现在,您可以查看是否给出了oeuvre.getMagasine()
或给出了oeuvre.getLivre()
。