2010-09-26 45 views
3

我在Doctrine2中使用Single Table Inheritance來存儲多個服務的OAuth憑據。我想使用該服務的ID作爲主鍵;然而,這在所有服務中並不是唯一的。Discriminator列可以成爲Doctrine2中的主鍵的一部分嗎?

我已經設置數據庫使用鑑別器列和服務的ID作爲主鍵,但我找不到一種方法來使Doctrine使用鑑別器列作爲關鍵(除了鑑別器列) 。我使用的docblock註釋,如果我添加了鑑別列作爲@Id場我得到一個錯誤:

Duplicate definition of column...in a field or discriminator column mapping. 

如果我只定義字段作爲鑑別列,任何重疊的服務ID更新所有匹配行。

反正不是僅僅使用一個自動生成它的值,使這項工作,其他的?

回答

2

不能,則descriminator列不能用作主鍵的一部分。

爲什麼你需要STI這個用例BTW?你必須創建按照您提供的開放式ID服務的一個新的類,聽起來很煩人:-)

+0

這並不壞,因爲各個服務類提供對服務的訪問,它們都只是擴展Mapped超類以保留常見的OAuth數據。這樣我將一個'$ client'與各種服務聯繫起來。因此,在laoding之後,一個調用'$ client-> twitter-> user-> show($ id)'的'$ client'將使用該'$ client'實體的OAuth憑證來獲取twitter用戶的數據。我相信還有其他更好的方法可以做到這一點,但目前它的運行情況良好。 – 2010-09-28 16:30:32

+2

我希望能夠使用鑑別器作爲PK的一部分:我有一個使用案例,其中一個表包含各種實體的翻譯,而我理想的PK將是(languageCode,discriminator,entityId)。同時,在這三個字段上自動遞增PK +一個唯一的鍵將會執行。 – Benjamin 2012-02-13 09:56:46

1

對於那些誰使用Hibernate,你可以(至少在JPA 2.1)。下面的代碼在我的環境perfeclty作品(休眠-的EntityManager 4.3.6.Final):

@Entity 
@Table(name = "CODIFICATIONS") 
@IdClass(CodificationId.class) 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = Codification.DISCRIMINATOR_COLUMN, discriminatorType = DiscriminatorType.INTEGER) 
public abstract class Codification implements Serializable { 

    public static final String DISCRIMINATOR_COLUMN = "TABLE_ID"; 

    private static final long serialVersionUID = 1L; 

    @Column(name = "CODIFICATION_ID") 
    protected Long codificationId; 

    @Id 
    @Column(name = DISCRIMINATOR_COLUMN, insertable = false, updatable = false) 
    protected Long tableId; 

    @Id 
    @Column(name = "CODE_ID", insertable = false, updatable = false) 
    protected Long codeId; 

    @Column(name = "LONG_NAME") 
    protected String longName; 

    @Column(name = "SHORT_NAME") 
    protected String shortName; 

} 

public class CodificationId implements Serializable { 

    private static final long serialVersionUID = 1L; 

    private Long tableId; 
    private Long codeId; 

    public Long getTableId() { 
     return tableId; 
    } 

    public void setTableId(Long tableId) { 
     this.tableId = tableId; 
    } 

    public Long getCodeId() { 
     return codeId; 
    } 

    public void setCodeId(Long codeId) { 
     this.codeId = codeId; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((tableId == null) ? 0 : tableId.hashCode()); 
     result = prime * result + ((codeId == null) ? 0 : codeId.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     CodificationId other = (CodificationId) obj; 
     if (tableId == null) { 
      if (other.tableId != null) 
       return false; 
     } else if (!tableId.equals(other.tableId)) 
      return false; 
     if (codeId == null) { 
      if (other.codeId != null) 
       return false; 
     } else if (!codeId.equals(other.codeId)) 
      return false; 
     return true; 
    } 

} 

@Entity 
@DiscriminatorValue(Status.DISCRIMINATOR_VALUE) 
public class Status extends Codification { 

    public static final String DISCRIMINATOR_VALUE = "2"; 

    private static final long serialVersionUID = 1L; 

} 

然後我配置的關聯狀態用下面的代碼:

@ManyToOne 
@JoinColumnsOrFormulas({ 
     @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = Codification.DISCRIMINATOR_COLUMN, value = Status.DISCRIMINATOR_VALUE)), 
     @JoinColumnOrFormula(column = @JoinColumn(name = "STATUS", referencedColumnName = "CODE_ID")) }) 
private Status status; 
相關問題