我有以下表(最重要的列仅示出,A & B不实名顺便说一句):@OneToMany关系使用一个@JoinColumn?
table A {
...
}
table B {
...
}
table METADATA {
KEY
VALUE
REF_A
REF_B
}
METADATA保持额外的键/值元数据两者表阿& B.键/需要值,因为我们必须处理一个我们不能在前面所述的创建列和B.
的实体是设置为(JPA采用Hibernate提供商)动态数据:
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)(确保Meta键只在A或B使用一次对于一个给定行):
CREATE UNIQUE INDEX METADATA_UNIQUE_KEY ON METADATA (METAKEY, REF_A, REF_B)
为创建索引要求要求所有列都是非空的。这是不适合用上述设计的情况下使用作为域逻辑将是一个在元数据被设定在A或B,因此,其中之一将总是为空。
当然可能的解决方案是将元数据分成两个表,一个是和一个B.但是我宁愿保持一个表,而不是仅仅有一个“REF”列其要么是A或B还有一个类型列说无论是对于A或B.将需要的类型,我们有一个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,
-Martin
谢谢你的详细和有用的答案。这比将元数据作为一个实体进行处理确实而且更简单。 但是,它也遭受了我们遇到的原始问题,它具有唯一的约束,以避免给定的A或B具有重复的“metaKey”。在DB2上将不可能添加以下索引: CREATE INDEX METADATA_UNIQUE_KEY ON METALLATA(METAKEY,TableA_id) 作为“TableA_id”可为空。 – lanzlord 2013-04-25 23:37:28
对不起,应该是: CREATE UNIQUE INDEX METADATA_UNIQUE_KEY ON METADATA(METAKEY,TableA_id) – lanzlord 2013-04-25 23:43:54
我想我理解有关唯一metaKey的问题。它是否只需要在同一个表(A或B)中唯一或唯一,包括两个表?如果是第一种情况,可以使用具有Map的解决方案。 java中的地图不允许重复的键(当你写第二个值时它只是覆盖第一个值),所以不需要在数据库级执行它。 –
German
2013-04-26 14:13:57