2010-09-26 18 views
3

J'utilise Single Table Inheritance dans Doctrine2 pour stocker les informations d'identification OAuth pour plusieurs services. J'aimerais utiliser l'identifiant du service comme clé primaire; Cependant, ce n'est pas unique dans tous les services. J'ai configuré la base de données pour utiliser la colonne discriminante et l'identifiant du service comme clé primaire, mais je n'arrive pas à faire en sorte que Doctrine utilise la colonne discriminante comme clé (en plus de la colonne discriminante) . J'utilise docblock annotations, et si j'ajoute la colonne discriminante comme un champ @Id je reçois une erreur:Une colonne Discriminator peut-elle faire partie de la clé primaire de Doctrine2?

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

Si je définis seulement le champ comme la colonne discriminante, tout ids de service qui se chevauchent sont mis à jour tous les correspondant lignes De toute façon pour faire ce travail, autre que d'utiliser simplement une valeur générée automatiquement?

Répondre

2

Vous ne pouvez pas, la colonne de descriminator ne peut pas être utilisée comme partie de la clé primaire. Pourquoi avez-vous besoin d'IST pour ce cas d'utilisation? Vous devez créer une nouvelle classe par service open-id que vous fournissez, cela semble très ennuyeux :-)

+0

Il est pas si mal, puisque les classes de service individuelles fournissent un accès au service, elles étendent simplement une superclasse mappée pour conserver les données OAuth communes. De cette façon, je relie un «client $» à divers services. Donc, après avoir codé un '$ client' appelant' $ client-> twitter-> user-> show ($ id) 'obtiendrait les données d'un utilisateur de Twitter en utilisant les informations d'identification OAuth de cette entité' $ client'. Je suis sûr qu'il existe d'autres/meilleures façons de le faire, mais cela fonctionne bien pour le moment. –

+2

J'aimerais aussi pouvoir utiliser le discriminateur dans le PK: j'ai un cas d'utilisation où une table contient des traductions pour différentes entités, et mon PK idéal serait (languageCode, discriminator, entityId). Pendant ce temps, un auto-incrément PK + une clé unique sur ces 3 champs fera l'affaire. – Benjamin

1

Pour ceux qui utilisent Hibernate, vous pouvez (au moins à partir de JPA 2.1). Le code suivant perfeclty fonctionne dans mon environnement (mise en veille prolongée-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; 

} 

Puis-je configurer une association au statut avec le code suivant:

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