5

Doctrine2 で単一テーブル継承を使用して、複数のサービスの OAuth 資格情報を保存しています。サービスの ID を主キーとして使用したいと考えています。ただし、これはすべてのサービスで一意というわけではありません。

ディスクリミネーター列とサービスの ID を主キーとして使用するようにデータベースをセットアップしましたが、Doctrine にディスクリミネーター列をキーとして (ディスクリミネーター列に加えて) 使用させる方法が見つかりません。docblock アノテーションを使用しています。識別子列を @Id フィールドとして追加すると、エラーが発生します。

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

フィールドを識別子列としてのみ定義すると、サービス ID が重複すると、一致するすべての行が更新されます。

とにかく、自動生成された it 値を使用する以外に、これを機能させるには?

4

2 に答える 2

2

できません。記述子列を主キーの一部として使用することはできません。

このユースケースで STI が必要なのはなぜですか? 提供する open-id サービスごとに 1 つの新しいクラスを作成する必要があります。かなり面倒に聞こえます :-)

于 2010-09-28T15:49:51.993 に答える
0

Hibernate を使用している場合は、(少なくとも JPA 2.1 以降では) 使用できます。次のコードは、私の環境 (hibernate-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;

}

次に、次のコードを使用して Status への関連付けを構成します。

@ManyToOne
@JoinColumnsOrFormulas({
        @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = Codification.DISCRIMINATOR_COLUMN, value = Status.DISCRIMINATOR_VALUE)),
        @JoinColumnOrFormula(column = @JoinColumn(name = "STATUS", referencedColumnName = "CODE_ID")) })
private Status status;
于 2014-08-22T12:48:42.793 に答える