Comment puis-je récupérer la clé étrangère à partir d'un APC ManyToOne cartographie sans frapper la table cible?
J'ai les deux annoté classes que j'utilise pour construire un graphique:
@Entity
@Table(name = "Edge")
public class Edge
{
/* some code omitted for brevity */
@ManyToOne
@JoinColumn(name = "ixNodeFrom", nullable = false)
private Node _nodFrom;
@ManyToOne
@JoinColumn(name = "ixNodeTo", nullable = false)
private Node _nodTo;
/* some code omitted for brevity */
}
@Entity
@Table(name = "Node")
public class Node
{
/* some code omitted for brevity */
@OneToMany(mappedBy = "_nodTo")
private Set<Edge> _rgInbound;
@OneToMany(mappedBy = "_nodFrom")
private Set<Edge> _rgOutbound;
/* some code omitted for brevity */
}
Maintenant, quand je construire un graphe, j'émets deux requêtes pour extraire toutes les lignes de deux tables et de configurer l'enfant et le parent, références, pour lequel j'ai besoin de l'id stocké dans le Edge
table.
Parce que je l'ai défini la relation entre les deux tables en JPA, accès au bord de l'objet pour obtenir les deux nœuds' id de l'objet de deux instructions SQL par edge, lorsque le fournisseur JPA paresseusement * les charges associées aux nœuds. Puisque j'ai déjà l'objet nœud, et les id ont déjà été chargés à partir du bord de la table, je veux ignorer ces questions, ils prennent un bien long temps pour les grandes graphiques.
J'ai essayé d'ajouter ces lignes à la Edge
classe, mais alors mon fournisseur JPA veut me faire une cartographie en lecture seule, et je n'arrive pas à trouver une façon de le faire:
@Column(name = "ixNodeTo")
private long _ixNodeTo;
@Column(name = "ixNodeFrom")
private long _ixNodeFrom;
Je suis en utilisant Eclipselink et MySQL, si il le faut.
**Le comportement par défaut pour @ManyToOne
est réellement impatient de chargement, voir La réponse de Pascal*
OriginalL'auteur Hanno Fietz | 2010-10-15
Vous devez vous connecter pour publier un commentaire.
, J'ai eu trois bonnes réponses qui ont été tout aussi utile, et, aujourd'hui, aucun n'étant répercutée vers le haut par le vote du public, je suis donc les fusionner ensemble ici pour une seule réponse:
a) Modifier la requête
Vous pouvez charger la totalité du graphique à la fois par l'évolution de la requête, donnant ainsi le fournisseur JPA une chance de réaliser qu'il a déjà tout dans la mémoire et n'a pas besoin de revenir à la DB:
(via axtavt)
b) l'Utilisation de champs en lecture seule pour les FKs
Chargement de la FKs dans leurs propres champs, comme décrit dans la question, fonctionne également si, en tant que fournisseur JPA est exigeant, les champs sont déclarés être en lecture seule, ce qui est fait de cette manière:
(via bravocharlie)
c) Utilisation de la propriété, de l'accès
Si vous utilisez l'accès à la propriété au lieu de domaine de l'accès, la JPA fournisseur obtient également une chance de réaliser qu'il a déjà le FK et n'a pas besoin d'aller chercher de l'objet référencé. En bref, l'accès à la propriété signifie que vous mettez les annotations JPA sur la lecture, ce qui "prometteurs" la JPA fournisseur de votre getter ne se fera pas et l'accès au reste de l'objet. Plus de détails dans cette question. Ce sera le travail de mise en veille prolongée, et pour Eclipselink, il va travailler (supposé à l'origine de réponse, confirmée expérimentalement par moi) avec le tissage de permis. (via Pascal Thivent)
En outre, comme Pascal le souligne dans sa réponse,
@ManyToOne
, contrairement à mon post original, n'est pas de lazy-loading, mais désireux de chargement par défaut, et de changer cela nécessite de tissage.Option b fonctionne parfaitement.
OriginalL'auteur Hanno Fietz
Avez-vous essayé
OriginalL'auteur bravocharlie
En théorie, un fournisseur JPA devrait être en mesure de ne pas déclencher une requête lors de l'appel de
comme il a déjà l'id (FK).
Je suis sûr à 100% Hibernate peut (en supposant que vous êtes en utilisant l'accès à la propriété). Dans le cas de EclipseLink, je ne sais pas (si elle le fait, il sera probablement nécessaire de tissage).
Noter que
@ManyToOne
utilise unEAGER
stratégie par défaut. Si vous souhaitez faireLAZY
, vous devez decalre explicitement (mais encore une fois, cela nécessitera de tissage de vos classes avec EclipseLink).OriginalL'auteur Pascal Thivent
Je pense que vous devriez essayer d'optimiser votre requête plutôt que de changer le mapping. Par exemple, la requête suivante extrait de tout le graphe à la fois (testé en mode veille prolongée):
OriginalL'auteur axtavt
Comment sur l'utilisation de getReference()?
Par exemple:
[1] Cela ne va pas déclencher une requête SQL pour récupérer les nodeFrom
OriginalL'auteur Mike Argyriou