I have an entity bean property which is a collection of another entity. I have not been able to find any way to deal with updating a collection where some of the objects in the collection already exist in the database, and some are newly added. As an example, imagine a web page where a user can enter the universities they attended. They may have gone through a reg page and selected just one. Now they are back to add more. So the first one they selected shows up on the edit page, and they now add some more via some + button or something. When they hit SAVE, the existing school they previously already selected is stored in the database, but now they need to add a few more selected schools. I am not sure if I have to try to load each school to see if it exists.. if it does, then call merge, if not then call persist.. something like:
Is the above the correct way to store a collection of values some of which may be new, some of which may contain changes to existing data?
I would go with em.merge(-) as it works in both cases - update and insert.
Joined: Nov 14, 2011
Thank you for replies.
It's odd that I can't find anything on em.merge indicating that it will persist if the object doesn't exist, or update if it does.
One thing I didn't go into detail about, but I will now to see if it changes the use of em.merge in all cases..
I use a delegation model behind my entity beans. That is, I have a POJO model object that is passed around from my rest front end to the EJB session bean back end. Because I package up my REST API as an SDK for client side developers as well (makes it easy with Jersey to use to work with my API), I use the pojo model without any ejb annotations in it as DTOs basically. The benefit is that I can get a REST request which builds out the POJO in a representation class, then pass the pojo as is to the entity as the model. Using method annotations on the entity beans, I delegate the get/set calls to the model get/set methods. So it looks something like:
Basically, the above allows me to reuse the User POJO object not only as a backing model in the rest representation class and the user entity bean, but it can also be used in other areas.. for example a struts 2 form being submitted with the user data fields, can use the same pojo to auto populate with. More so, I can bundle up the User pojo in a rest client side SDK allowing developers to utilize the same pojo when say creating a User. I could be wrong, but if I were to use the UserEntity object all over, the SDK that wraps it up would require the dependency on the javax.ejb.* entity annotations in order to work on the client side. I don't want the ejb dependency to be required on the client side.
So..the reason to explain all this? Well, in my case, this way of doing things means EVERY entity is "detached" via the pojo model that is used in between the tiers. So if I return a List<User> response back which would be something like <users><user><username>...</username></user><user><username>...</username></user></users> and the client side decided to add a couple new users, but also update some existing users.. they would send in a new List<User> with update users and new users..perhaps some removed. THUS.. the whole point of this post is to figure out if there is a way to update existing entities, add new ones and perhaps even delete ones not in the list passed in.. and if em.merge() does this? Or do I have to loop through the list, looking up each object to see if it exists.. if so, update it (merge) and if not, persist it. As well.. to handle deletion I'd have to get the list of ALL objects in the DB and figure out those missing in the passed in list to remove them from the DB.
Sorry for the long winded explanation, not sure how else to detail what it is I am trying to do.
The merge operation allows for the propagation of state from detached entities onto persistent entities
managed by the entity manager.
The semantics of the merge operation applied to an entity X are as follows:
- If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X'
of the same identity or a new managed copy X' of X is created.
- If X is a new entity instance, a new managed entity instance X' is created and the state of X is
copied into the new managed entity instance X'. (...)
Joined: Nov 14, 2011
Funny.. After you and the other poster said merge() should persist.. I had better search terms and did find an article regarding using Merge and that basically you should use merge except in cases where you need to persist/flush/refresh to get a generated ID then set the persisted entity on another entity relationship before it persists. Makes sense now, I wish my ejb 3 book had explained this better.