Meilleure façon de faire face JPA fusion?
Je suis nouveau à l'ensemble de la JPA chose donc j'ai plusieurs questions sur la meilleure façon de gérer JPA de fusion et de persister.
- J'ai un objet utilisateur qui doit être mis à jour (certaines valeurs comme la date et le nom). Dois-je les fusionner l'objet passé en premier ou est-il plus sûr de trouver le nouvel objet?
Actuellement mon code pour la mise à jour d'un utilisateur ressemble à ceci:
public void updateUserName(User user, String name) { //maybe first merge it? user.setName(name); user.setChangeDate(new Date()); em.merge(user); }
Comment puis-je être sûr que l'utilisateur n'a pas été manipulé avant la mise à jour de la méthode est appelée? Est-il sécuritaire de faire quelque chose comme ceci:
public void updateUserName(int userId, String name) { User user = em.getReference(User.class, userId); user.setName(name); user.setChangeDate(new Date()); em.merge(user); }
Peut-être d'autres solutions? J'ai regardé plusieurs vidéos et a vu de nombreux exemples, mais ils étaient tous différents et personne n'a expliqué ce que la meilleure pratique est.
- Quelle est la meilleure approche pour ajouter des enfants à des relations? Par exemple, mon objet utilisateur a une connexion à plusieurs groupes. Devrais-je appeler la JPA gestionnaire pour les utilisateurs et il suffit d'ajouter le nouveau groupe à la liste de groupe utilisateur ou dois-je créer le groupe dans le cadre d'un groupe de gestionnaire de persister et de l'ajouter manuellement à mon objet utilisateur?
Espère que quelqu'un ici a une idée 😉
OriginalL'auteur ManuPanu | 2013-04-05
Vous devez vous connecter pour publier un commentaire.
Cela dépend de ce que vous voulez atteindre et comment beaucoup d'informations que vous avez sur l'origine de l'objet que vous essayez de fusionner.
Tout d'abord, si vous appelez
em.merge(user)
dans la première ligne de votre méthode ou à la fin il n'a pas d'importance. Si vous utilisez JTA et CMT, votre organisme sera mis à jour lors de l'invocation de méthode de finitions. La seule différence est que si vous appelezem.merge(user)
avant de changer d'utilisateur, vous devez utiliser le retour de l'instance au lieu de votre paramètre, donc soit c'est:ou
Maintenant sur la mise à jour de l'entité.
Si vous voulez juste de mettre à jour certains champs de votre entité - utiliser la deuxième méthode est plus sûre. Vous ne pouvez pas être sûr si un client de votre méthode n'a pas modifié certains autres domaines de votre entité. Par conséquent,
em.merge(-)
les mises à jour ainsi ce qui pourrait ne pas être ce que tu voulais faire.Sur l'autre main, si vous acceptez toutes les modifications faites par l'utilisateur et juste remplacer /ajouter certaines propriétés comme
changeDate
dans votre exemple, la première approche est aussi très bien (fusion entité entière passée à la méthode des affaires.) Cela dépend vraiment de votre cas d'utilisation.Je suppose que cela dépend de vos paramètres en cascade. Si vous voulez automatiquement persistent /fusionner tous les
Groups
chaque fois que leUser
entité est changé - c'est sûr il suffit de l'ajouter à la collection de l'Utilisateur (quelque chose commeUser#addGroup(Group g) { groups.add(g)}
. Si vous ne voulez pas en cascade, vous pouvez toujours créer vos propres méthodes de propagation de l'autre côté de la relation. Il pourrait être quelque chose comme:User#addGroup(Group g)
qui appelle automatiquementg.addUser(this);
.OriginalL'auteur Piotr Nowicki
Question 1
merge
méthode doit être appelée sur un détaché entité.merge
méthode retourne l'objet fusionné attaché à l'entityManager.Ça veut dire quoi ?
Une entité est détaché dès que l'entityManager vous utilisez pour aller chercher il est fermé. (c'est à dire la plupart du temps parce que vous chercher dans une transaction précédente).
Dans votre deuxième échantillon de code: l'utilisateur est connecté (parce que vous venez le chercher) et donc l'appel de l'opération de fusion est inutile. (BTW : il n'est pas
getReference
maisfind
)Dans votre premier exemple: nous ne connaissons pas l'état de l'utilisateur (détaché de l'entité ou pas ?). Si elle est détachée, elle un sens pour appeler
merge
, mais attention à ce quemerge
ne pas modifier l'objet passé en argument. Voici donc ma version de votre premier échantillon:Question 2
Peut-être quelques exemples de code pour expliquer ce que vous entendez par jpa gestionnaire peut nous aider à comprendre votre souci. De toute façon, je vais essayer de vous aider.
Si vous avez un utilisateur persistantes et vous avez besoin de créer un nouveau groupe, et de l'associer avec de la persistance de l'utilisateur:
Si vous avez un utilisateur persistantes et persistant groupe et vous avez besoin de les associer:
Considérations générales
Les meilleures pratiques concernant tout cela dépend vraiment de vous gérer les transactions (et donc le cycle de vie de l'entityManager) vs le cycle de vie de vos objets.
La plupart du temps: un entityManager est vraiment un très court temps de vie à l'objet. D'autre part, votre business objects peuvent vivre plus longtemps et donc, vous aurez à composer de fusion (et en faisant attention sur le fait que la fusion ne pas modifier l'objet passé en argument !!!).
Vous pouvez décider de récupérer et de modifier les objets dans la même transaction (c'est à dire avec le même entityManager): il signifie beaucoup plus d'accès de base de données et, cette stratégie doit généralement être combiné avec un cache de second niveau pour des raisons de performances. Mais dans ce cas, vous n'aurez pas à appeler de fusion.
J'espère que cette aide.
OriginalL'auteur ben75