我有以下表格(仅显示最重要的列,A 和 B 不是真实姓名顺便说一句):
table A {
...
}
table B {
...
}
table METADATA {
KEY
VALUE
REF_A
REF_B
}
METADATA 为表 A 和 B 保存额外的键/值元数据。键/值是必需的,因为我们必须处理无法预先在 A 和 B 中创建列的动态数据。
实体设置为(JPA 使用休眠作为提供者):
interface Entity {
...
getId()
...
}
class A implements Entity {
...
@OneToMany(cascade = {ALL}, mappedBy = "a", orphanRemoval = true, fetch = LAZY)
private List<MetaData> metaData;
...
@Override
public List<MetaData> getMetaData() {
return metaData;
}
...
}
class B implements Entity {
...
@OneToMany(cascade = {ALL}, mappedBy = "b", orphanRemoval = true, fetch = LAZY)
private List<MetaData> metaData;
...
@Override
public List<MetaData> getMetaData() {
return metaData;
}
...
}
class MetaData implements Entity {
...
@ManyToOne
@JoinColumn(name = "REF_A", nullable = true)
private A a;
@ManyToOne
@JoinColumn(name = "REF_B", nullable = true)
private B b;
...
}
此设置工作正常。但是,我们在某些数据库(例如 DB2)上遇到了我们创建唯一索引的问题(以确保元键仅用于 A 或 B 中的给定行一次):
CREATE UNIQUE INDEX METADATA_UNIQUE_KEY ON METADATA (METAKEY, REF_A, REF_B)
因为创建索引需要所有列都是非空的。与上述设计一起使用的情况并非如此,因为域逻辑将元数据设置在 A 或 B 上,因此其中之一将始终为空。
可能的解决方案当然是将元数据拆分为两个表,一个用于 A,一个用于 B。但是我更愿意保留一个表,而不是只有一个“REF”列,它可以是 A 或 B 以及TYPE 列来说明它是 A 还是 B 的元数据。 TYPE 是必需的,因为我们对每个表都有单独的 id 序列,并且 A 和 B 可以获得相同的技术 id,因此会混淆数据。
我的问题是 - 有没有办法用 JPA 进行设置?
对于基于单表的继承,有一个 @DiscriminatorValue 可用于区分特定存储的子类,这里也可以使用吗?我正在寻找类似的东西:
table A {
...
}
table B {
...
}
table METADATA {
KEY
VALUE
REF
TYPE
}
@DiscriminatorValue("A")
class A implements Entity {
...
@OneToMany(cascade = {ALL}, mappedBy = "entity", orphanRemoval = true, fetch = LAZY)
private List<MetaData> metaData;
...
@Override
public List<MetaData> getMetaData() {
return metaData;
}
...
}
@DiscriminatorValue("B")
class B implements Entity {
...
@OneToMany(cascade = {ALL}, mappedBy = "entity", orphanRemoval = true, fetch = LAZY)
private List<MetaData> metaData;
...
@Override
public List<MetaData> getMetaData() {
return metaData;
}
...
}
class MetaData implements Entity {
...
@ManyToOne
@JoinColumn(name = "REF", nullable = true)
private Entity entity;
@DiscriminatorColumn(name="TYPE", discriminatorType=STRING, length=20)
private String type;
...
}
所以基本上当为 A 插入元数据时,将使用此 SQL:
INSERT INTO METADATA (KEY, VALUE, REF, TYPE) VALUES ("metaKey", "metaValue", 1, "A")
欢迎任何建议。
Rgs,
-马丁