49 votes

Hibernate - Clés étrangères au lieu d'Entités

Actuellement, Hibernate me permet de charger des objets définis par des relations *-to-one directement avec

entity1.getEntity2()

Est-il possible d'obtenir la clé étrangère au lieu de l'objet ?

L'approche actuelle que je vois consiste à ajouter un addint à ma cartographie :

@JoinColumn(name="message_key")
@ManyToOne(targetEntity=Message.class,fetch=FetchType.LAZY)
private Message message;  //these lines currently exist

@Column(name="message_key")
private Long message_fk; //the idea is to add those 2 lines

Existe-t-il une meilleure approche pour obtenir la clé étrangère, ou est-ce la seule ?

46voto

Affe Points 24993

Oui, vous pouvez le faire. Vous devez juste préciser à Hibernate quel est le mappage qu'il est censé maintenir, comme ceci :

@Column(name="message_key", updatable=false, insertable=false)
private Long message_fk;

19voto

Marcelo Points 6708

Si vous voulez toujours une référence à votre entité mais ne voulez pas la charger depuis la base de données juste pour obtenir la clé étrangère, votre approche est la bonne. Ajoutez insertable et updatabale = false à l'attribut Column pour éviter de perdre la référence correcte à une entité.

@JoinColumn(name = "message_key")
@ManyToOne(targetEntity = Messages.class, fetch = FetchType.LAZY)
private Messages message;

@Column(name = "message_key", insertable = false, updatable = false)
private Long message_fk;

5voto

RobertG Points 1118

En fait, le comportement par défaut d'Hibernate est de ne charger que la clé étrangère au lieu de l'objet message si le FetchType est LAZY. C'est pourquoi il existe des proxies pour les objets à charger lorsque vous spécifiez LAZY FetchType.

La clé étrangère n'est pas visible directement, mais il s'agit bien sûr de la clé de l'objet situé à l'extrémité "un" de la relation OneToMany.

Cependant, avec un type d'accès basé sur les champs (par exemple, dans votre cas, où les annotations sont placées sur les champs), il y a un problème non résolu dans Hibernate : Hibernate charge l'objet entier derrière le proxy depuis la base de données. ( http://blog.xebia.com/2009/06/13/jpa-implementation-patterns-field-access-vs-property-access/ )

Ma suggestion concrète serait (car, par exemple, la "bonne" réponse n'a pas fonctionné dans mon cas) :

  • Utilisez directement l'objet message, car Hibernate ne le chargera que si des données sans clé étrangère sont nécessaires. Ne spécifiez pas de champ supplémentaire pour la clé étrangère.
  • Changez la classe pour utiliser l'accès aux propriétés, c'est-à-dire définissez des getters et setters, et mettez vos annotations des champs aux getters.

2voto

Jesse Webb Points 8015
Long fk = entity1.getEntity2().getId();

Cela devrait fonctionner. Cela ne fonctionnerait que si des clés primaires composites étaient référencées comme des clés étrangères, mais votre solution ne fonctionnerait pas non plus dans ce cas. Si l'on considère ma solution, même une clé composite ne serait pas si moche.

Long fkField1 = entity1.getEntity2().getCol1();
String fkField2 = entity1.getEntity2().getCol2();

Quelque chose comme ça marchera.

EDIT : En réfléchissant davantage à la solution que vous proposez, elle ne fonctionnerait pas de toute façon, car Hibernate essaie déjà de créer automatiquement un champ FK pour une relation mappée, donc définir une autre @Column essaierait simplement de se lier à une deuxième colonne portant le même nom.

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