代码之家  ›  专栏  ›  技术社区  ›  Tim Lytle

在doctrine2中,鉴别器列是否可以作为主键的一部分?

  •  4
  • Tim Lytle  · 技术社区  · 14 年前

    我在用 Single Table Inheritance 在doctrine2中存储多个服务的OAuth凭据。我想使用服务的ID作为主键;但是,在所有服务中,这不是唯一的。

    我已经设置了数据库,以使用鉴别器列和服务的ID作为主键,但是我找不到一种方法可以使条令使用鉴别器列作为键(除了鉴别器列之外)。我正在使用docblock注释,如果我将鉴别器列添加为@id字段,则会得到一个错误:

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

    如果我只将字段定义为鉴别器列,那么任何重叠的服务ID都会更新所有匹配的行。

    不管怎样,除了使用自动生成的IT值之外,还要让它工作吗?

    2 回复  |  直到 10 年前
        1
  •  2
  •   beberlei    14 年前

    不能,Descriminator列不能用作主键的一部分。

    为什么这个用例btw需要sti?您必须为您提供的每个开放ID服务创建一个新类,听起来很烦人:-)

        2
  •  2
  •   Jean-Christophe    10 年前

    对于使用Hibernate的用户,您可以(至少是JPA2.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;
    
    }
    

    然后我用以下代码配置与状态的关联:

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