Может ли столбец дискриминатора быть частью первичного ключа в Doctrine2? - PullRequest
4 голосов
/ 27 сентября 2010

Я использую Наследование отдельных таблиц в Doctrine2 для хранения учетных данных OAuth для нескольких служб. Я хотел бы использовать идентификатор службы в качестве первичного ключа; однако, это не уникально для всех сервисов.

Я настроил базу данных для использования столбца дискриминатора и идентификатора службы в качестве первичного ключа, но не могу найти способ заставить Doctrine использовать столбец дискриминатора в качестве ключа (в дополнение к столбцу дискриминатора). Я использую аннотации docblock, и если я добавляю столбец дискриминатора как поле @Id, я получаю сообщение об ошибке:

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

Если я определю только поле как столбец дискриминатора, все перекрывающиеся идентификаторы службы обновят все соответствующие строки.

В любом случае, чтобы это работало, кроме использования автоматически сгенерированного значения?

Ответы [ 2 ]

2 голосов
/ 22 августа 2014

Для тех, кто использует Hibernate, вы можете (по крайней мере, начиная с JPA 2.1).Следующий код perfeclty работает в моей среде (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;
2 голосов
/ 28 сентября 2010

Вы не можете, столбец дескриптора не может использоваться как часть первичного ключа.

Зачем вам нужен STI для этого варианта использования?Вы должны создать один новый класс для каждого предоставляемого вами сервиса open-id, звучит довольно раздражающе: -)

...