When I have an Entity with relationships I don't know which is the best way to save changes to DB.
Here is a simplified entity. Please consider I have made little changes to the code to post it here and I can have introduced some errors.
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;
As you can see it is linked to other 2 entities with a OneToMany and OneToOne relationships. I'm using Glassfish with jta so transactions and entityManagers are managed by the container.
At a time I have a detached (JPA terminology) Permessitemporanei instance in memory. I have to persist the following changes to the database: 1- the associated ingressiconpermesso must be deleted 2- a new ingressiconpermesso must be created 3- statopermesso field must be updated 4- a new Accessiconpermesso must be added to the collection accessiconpermessoCollection
Which is the best way of doing so ? Perhaps I can do all necessary changes in the Permessitemporanei instance an merge it but I had many troubles doing so and start to think it is not the right side of the relationships to persist changes. For me it more natural to save an object at a time, so eliminating all those cascade = CascadeType.ALL.
Suppose my Permessitemporanei instance is called 'permesso' ; my code is something like this:
- getEntityManager().remove(permesso.ingressiconpermesso);
- getEntityManager().persist(a new Ingressiconpermesso );
- getEntityManager().merge(permesso) // once its statopermesso field has been updated;
- getEntityManager().perist(a new Accessiconpermesso );
Obviously this way I have to manually update the in memory 'permesso' with all the changes I made on Database.
Is there a better approach ?
By the way all the JPA relationships I have seen are bidirectional. Can I make them unidirectional ? To put it in other words can I safely eliminate Code:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "iDpermesso") private Collection accessiconpermessoCollection;
from the Permessitemporanei entity preserving it on the Accessiconper开发者_高级运维messo entity or do i break JPA ?
Thanks Filippo
The way I like to approach complex entity updates is to:
- Start a new transaction.
- Make all the changes that I want to make against my Objects in memory.
- Tell the
EntityManager
what I did once I'm done. - Commit the transaction.
But first things first, you will likely have a much easier time of things if you get a non-detached Permessitemporanei
instance to start with:
Permessitemporanei persistentInstance = em.find(Permessitemporanei.class, detachedInstance.getId());
Then do all of your changes in memory, inform the EntityManager
, and commit the 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();
To answer your other question, no, you generally do not need to annotate both sides of a relationship. You can remove your @OneToMany
annotation if you want, and it shouldn't break anything (as far as JPA cares, anyways...you may well have application code that relies upon this Collection
being present and properly populated, and removing the JPA mapping will of course break any such code). However, I don't really think you gain anything by removing it, so I'd recommend leaving it alone.
精彩评论