2011-08-01 5 views
0

Lorsque j'ai une entité avec des relations, je ne sais pas quel est le meilleur moyen d'enregistrer les modifications apportées à la base de données.Meilleure façon d'utiliser JPA avec les relations

Voici une entité simplifiée. Veuillez considérer que j'ai apporté quelques modifications au code pour l'afficher ici et que j'ai pu introduire quelques erreurs.

public class Permessitemporanei implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "ID_permesso") 
    private Integer iDpermesso; 
    @Column(name = "Stato_permesso") 
    private Integer statopermesso; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "iDpermesso") 
    private Collection<Accessiconpermesso> accessiconpermessoCollection; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "iDpermesso") 
    private Ingressiconpermesso ingressiconpermesso; 

Comme vous pouvez le voir est lié à d'autres 2 entités avec une OneToMany et les relations ONEtoONE. J'utilise Glassfish avec jta pour que les transactions et les entityManagers soient gérés par le conteneur.

A un moment donné, j'ai une instance détachée (terminologie JPA) Permessitemporanei en mémoire. Je dois persister les modifications suivantes à la base de données: 1- la ingressiconpermesso associé doit être supprimé 2- une nouvelle ingressiconpermesso doit être créé 3- champ statopermesso doit être mis à jour 4- un nouveau Accessiconpermesso doit être ajouté à la collection accessiconpermessoCollection

Quelle est la meilleure façon de le faire? Peut-être que je peux faire tous les changements nécessaires dans l'instance de Permessitemporanei et la fusionner, mais j'ai eu beaucoup de problèmes à le faire et commencer à penser que ce n'est pas le bon côté des relations de persister les changements. Pour moi, il est plus naturel de sauvegarder un objet à la fois, éliminant ainsi toutes les cascade = CascadeType.ALL. Supposons que mon instance de Permessitemporanei s'appelle "permesso"; mon code est quelque chose comme ceci:

  1. getEntityManager(). remove (permesso.ingressiconpermesso); GetEntityManager(). Persist (un nouveau Ingressiconpermesso)
  2. getEntityManager(). Merge (permesso) // une fois que son champ statopermesso a été mis à jour; GetEntityManager(). Perist (un nouveau Accessiconpermesso)

De toute évidence, de cette façon, je dois mettre à jour manuellement la mémoire 'permesso' avec toutes les modifications que j'ai apportées à la base de données.

Y a-t-il une meilleure approche? Par ailleurs, toutes les relations JPA que j'ai vues sont bidirectionnelles. Puis-je les rendre unidirectionnels? Pour le dire autrement dit ce que je peux éliminer en toute sécurité code:

@OneToMany (cascade = CascadeType.ALL, mappedBy = "iDpermesso") de accessiconpermessoCollection Collection privée ;

de l'entité Permessitemporanei en le conservant sur l'entité Accessiconpermesso ou est-ce que je brise JPA?

Merci Filippo

Répondre

3

La façon dont je voudrais aborder les mises à jour des entités complexes consiste à:

  1. Démarrer une nouvelle transaction.
  2. Effectuez tous les changements que je souhaite apporter à mes objets en mémoire.
  3. Dites au EntityManager ce que j'ai fait une fois que j'ai terminé.
  4. Validez la transaction.

Mais tout d'abord, vous aurez probablement un temps beaucoup plus facile des choses si vous obtenez une Permessitemporanei instance non détachée pour commencer:

Permessitemporanei persistentInstance = em.find(Permessitemporanei.class, detachedInstance.getId()); 

font alors tous vos changements dans la mémoire, informer le EntityManager et valider la transaction:

//begin a transaction 
em.getTransaction().begin(); 

//remember the old Ingressiconpermesso instance 
Ingressiconpermesso oldIngression = persistentInstance.getIngressiconpermesso(); 

//create a new Ingressiconpermesso instance 
Ingressiconpermesso newIngression = new Ingressiconpermesso(); 
//call newIngression.set...() methods here 

//associate the new Ingressiconpermesso with the Permessitemporanei 
persistentInstance.setIngressiconpermesso(newIngression); 

//update statopermesso 
persistentInstance.setStatopermesso(7); //replace '7' with whatever the real value is 

//add a new Accessiconpermesso 
Accessiconpermesso accession = new Accessiconpermesso(); 
//call accession.set...() methods here 

//associate the Accessiconpermesso with the Permessitemporanei 
accession.setPermissitemporanei(persistentInstance); 

//now tell the EntityManager what we did 
em.remove(oldIngression);  //delete the old Ingressiconpermesso 
em.persist(newIngression);  //add the new Ingressiconpermesso 
em.persist(accession);   //add the Accessiconpermesso 
em.merge(persistentInstance); //update the Permessitemporanei 

//commit the transaction 
em.getTransaction().commit(); 

pour répondre à votre autre question, non, vous ne généralement pas besoin d'annoter les deux côtés d'une relation. Vous pouvez supprimer votre annotation @OneToMany si vous le souhaitez, et cela ne devrait rien casser (pour autant que JPA se soucie, de toute façon ... vous pouvez avoir un code d'application qui repose sur cette Collection étant présent et correctement rempli, et supprimant le mappage JPA va bien sûr casser un tel code). Cependant, je ne pense pas que vous gagniez quoi que ce soit en l'enlevant, donc je vous recommande de le laisser seul.

+0

Merci beaucoup Aroth, aussi parce que vous avez passé du temps à écrire du code pour mieux comprendre. J'aurais besoin d'un peu plus d'aide. Tout d'abord une question triviale. Je suppose que vous avez oublié de mettre à jour l'accessiconpermessoCollection en mémoire, n'est-ce pas? – Filippo

+0

Deuxièmement, vous effectuez une opération remove/persist/merge sur tous les objets. Je suppose que cela implique que vous n'utilisez pas la cascade .. et c'est la façon dont je remplis plus à l'aise avec. – Filippo

+0

Encore une fois sur la relation oneToMany liée à une clé étrangère sur DB. Si je ne suis pas intéressé par la conservation de la cohérence des objets en mémoire parce que je prévois de les actualiser/recharger, dois-je quand même écrire 'persistentInstance.getAccessiconpermessoCollection.add (accession)' à partir de ma première question? JPA se plaint-il lorsque je fusionne persistInstance si sa collection n'est pas mise à jour? – Filippo

Questions connexes