99 votes

A quoi sert referencedColumnName dans JPA ?

Dans JPA, il existe un attribut appelé referencedColumnName qui peuvent être réglées sur @JoinColumn, @PrimaryKeyJoinColumn Quelle est l'idée derrière ce paramètre ? Quelqu'un peut-il donner un bon exemple d'utilisation ?

91voto

Firo Points 21003

Il permet de spécifier une autre colonne comme colonne par défaut id de l'autre tableau, par exemple, considérons ce qui suit

TableA
  id int identity
  tableb_key varchar

TableB
  id int identity
  key varchar unique

// in class for TableA
@JoinColumn(name="tableb_key", referencedColumnName="key")

55voto

EAmez Points 110

La propriété "referencedColumnName" est le nom de la colonne de la table à laquelle vous faites référence avec la colonne que vous annotez. En d'autres termes, il s'agit de la colonne référencée dans la table de destination. Imaginez quelque chose comme ceci : des voitures et des personnes. Une personne peut avoir plusieurs voitures, mais une voiture n'appartient qu'à une seule personne (désolé, je n'aime pas que quelqu'un d'autre conduise ma voiture).

Personne de table
name char(64) primary key
âge int

Voiture de table
car_registration char(32) primary key
marque_voiture (char 64)
modèle_de_voiture (char64)
owner_name char(64) foreign key references Personne(nom)

Lorsque vous mettez en œuvre des classes, vous aurez quelque chose comme

class Person{
   ...
}

class Car{
    ...
    @ManyToOne
    @JoinColumn([column]name="owner_name", referencedColumnName="name")
    private Person owner;
}

EDIT : comme l'a fait remarquer @searchengine27, columnName n'existe pas en tant que champ dans la section sur la persistance de la documentation Java7. Je ne me souviens plus où j'ai pris cette propriété, mais je me souviens l'avoir utilisée, c'est pourquoi je la laisse dans mon exemple.

25voto

JMelnik Points 3870

Citation API sur referencedColumnName :

Le nom de la colonne référencée par cette clé étrangère colonne.

Défaut (ne s'applique que si sing Le même nom que la colonne de clé primaire de la table référencée.

Q/A

Où serait-il utilisé ?

Lorsqu'il y a un PK composite dans la table référencée vous devez alors spécifier le nom de la colonne à laquelle vous faites référence.

20voto

  • name pointe sur la colonne contenant l'association, c'est-à-dire le nom de la colonne de la clé étrangère.
  • referencedColumnName pointe sur la colonne associée dans l'entité associée/référencée, c'est-à-dire le nom de la colonne de la clé primaire.

Vous n'êtes pas tenu de remplir le referencedColumnName si l'entité référencée a une seule colonne comme PK, parce qu'il n'y a aucun doute sur la colonne à laquelle elle fait référence (c'est-à-dire la colonne Address ID à colonne unique).

@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }

Toutefois, si l'entité référencée a une PK qui s'étend sur plusieurs colonnes, l'ordre dans lequel vous indiquez @JoinColumn a de l'importance. Il pourrait fonctionner sans les referencedColumnName spécifié, mais c'est une question de chance. Vous devriez donc le cartographier de la manière suivante :

@ManyToOne
@JoinColumns({
    @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
    @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
})
public Address getAddress() { return address; }

ou en cas de ManyToMany :

@ManyToMany
@JoinTable(
    name="CUST_ADDR",
    joinColumns=
        @JoinColumn(name="CUST_ID"),
    inverseJoinColumns={
        @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
        @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
    }
)

Exemple concret

Deux requêtes générées par Hibernate à partir du même mappage de table de jointure, toutes deux sans colonne référencée spécifiée. Seul l'ordre de @JoinColumn ont été modifiées.

/* load collection Client.emails */ 
select 
emails0_.id_client as id1_18_1_,
emails0_.rev as rev18_1_,
emails0_.id_email as id3_1_,
email1_.id_email as id1_6_0_

from client_email emails0_ 
inner join email email1_ on emails0_.id_email=email1_.id_email 

where emails0_.id_client='2' and 
emails0_.rev='18'

/* load collection Client.emails */ 
select
emails0_.rev as rev18_1_,
emails0_.id_client as id2_18_1_,
emails0_.id_email as id3_1_, 
email1_.id_email as id1_6_0_

from client_email emails0_ 
inner join email email1_ on emails0_.id_email=email1_.id_email 

where emails0_.rev='2' and 
emails0_.id_client='18'

Nous interrogeons une table de jointure pour obtenir les courriels des clients. La table {2, 18} est l'identifiant composite du client. L'ordre des noms de colonnes est déterminé par l'ordre des colonnes @JoinColumn annotations. L'ordre des deux entiers est toujours le même, probablement trié par hibernate et c'est pourquoi un alignement correct avec les colonnes de la table de jonction est nécessaire et nous ne pouvons pas ou ne devrions pas nous fier à l'ordre de mappage.

Ce qui est intéressant, c'est que l'ordre des nombres entiers ne correspond pas à l'ordre dans lequel ils sont représentés dans l'entité. {18, 2} . Il semble donc qu'Hibernate trie les noms des colonnes avant de les utiliser dans la requête. Si c'est vrai et que vous voulez ordonner vos @JoinColumn de la même manière que vous n'auriez pas besoin de referencedColumnName mais je ne le dis qu'à titre d'illustration.

Remplissage adéquat referencedColumnName permettent d'obtenir exactement la même requête sans l'ambiguïté, dans mon cas la deuxième requête ( rev = 2 , id_client = 18 ).

2voto

Progster219 Points 40

Pour un exemple d'utilisation de JPA 2.x pour le cas général de deux tables, avec un @OneToMany jointure unidirectionnelle voir https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.x_unidirectional_OneToMany_relationship_annotations

Capture d'écran de l'article JPA de WikiBooks : Exemple d'une base de données de relations unidirectionnelles OneToMany JPA 2.x

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X