Discriminator列可以成为Doctrine2中的主键的一部分吗?
问题描述:
我在Doctrine2中使用Single Table Inheritance来存储多个服务的OAuth凭据。我想使用该服务的ID作为主键;然而,这在所有服务中并不是唯一的。Discriminator列可以成为Doctrine2中的主键的一部分吗?
我已经设置数据库使用鉴别器列和服务的ID作为主键,但我找不到一种方法来使Doctrine使用鉴别器列作为关键(除了鉴别器列) 。我使用的docblock注释,如果我添加了鉴别列作为@Id场我得到一个错误:
Duplicate definition of column...in a field or discriminator column mapping.
如果我只定义字段作为鉴别列,任何重叠的服务ID更新所有匹配行。
反正不是仅仅使用一个自动生成它的值,使这项工作,其他的?
答
不能,则descriminator列不能用作主键的一部分。
为什么你需要STI这个用例BTW?你必须创建按照您提供的开放式ID服务的一个新的类,听起来很烦人:-)
答
对于那些谁使用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;
这并不坏,因为各个服务类提供对服务的访问,它们都只是扩展Mapped超类以保留常见的OAuth数据。这样我将一个'$ client'与各种服务联系起来。因此,在laoding之后,一个调用'$ client-> twitter-> user-> show($ id)'的'$ client'将使用该'$ client'实体的OAuth凭证来获取twitter用户的数据。我相信还有其他更好的方法可以做到这一点,但目前它的运行情况良好。 – 2010-09-28 16:30:32
我希望能够使用鉴别器作为PK的一部分:我有一个使用案例,其中一个表包含各种实体的翻译,而我理想的PK将是(languageCode,discriminator,entityId)。同时,在这三个字段上自动递增PK +一个唯一的键将会执行。 – Benjamin 2012-02-13 09:56:46