我有以下表(最重要的列僅示出,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