Mitesh Meswani wrote:
Allen Gilliland wrote:
Mitesh Meswani wrote:
Dave wrote:
On 1/18/07, Mitesh Meswani <[EMAIL PROTECTED]> wrote:
> if(object.id != null)
> update()
> else
> save()
This would be true if the id is generated as is the case with Roller.
For objects where id is user supplied, above algorithm can not be
used.
Thats the reason some frameworks (for example JPA) does not provide
equivalent of saveOrUpdate() method.
Yes, that is true and it is the case with the property object, whose
ID is the name property.
And, we can't rely on object.id because we don't know which field is
the id. So, for JPA you'd have to do something like this in the store
method:
EntityManager em = getEntityManager(true);
if (!em.contains(obj)) {
// If entity is not managed we can assume it is new
em.persist(obj);
}
return obj;
Above has a performance penalty to pay and it assumes that no
detached object will be ever passed to store(). Currently, I don't
think that is true. For example, I found following with a quick search
Class MaintenanceAction {
....
public ActionForward flushCache(
ActionMapping mapping,
ActionForm actionForm,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
try {
RollerRequest rreq =
RollerRequest.getRollerRequest(request);
-----> WebsiteData website = rreq.getWebsite(); // I think this
is a detached object
RollerSession rses = RollerSession.getRollerSession(request);
if ( rses.isUserAuthorizedToAdmin(website) ) {
// some caches are based on weblog
last-modified, so update it
website.setLastModified(new Date());
try {
UserManager umgr =
RollerFactory.getRoller().getUserManager();
-----> umgr.saveWebsite(website); // The save will
not work as it will end up calling persist
Actually, that shouldn't be a detached object because the
RollerRequest class should be querying for the object on each
request.In any case though, the main point is as Dave suggested
before, we will *NOT* support the saving of detached objects anymore
and anywhere that does it now is considered a bug and needs to be fixed.
Great. So, the approach suggested by Dave should work. I remember seeing
detached objects being used in the test code which we can fix as required.
But, I still think that the code will be cleaner if we distinguish
between saving a new object vs. updating an existing object. Most of the
calls to Manager#save() are on managed object and can be removed.
The JPA implementation currently use the information about whether save
is called for insert or update to maintain relationships as below.
Class DatamapperWeblogManagerImpl {
.....
public void saveWeblogCategory(WeblogCategoryData cat)
throws RollerException {
......
if(!PersistentObjectHelper.isObjectPersistent(cat)) { <<-- A
workaround to findout whether we are here for insert or update
// Newly added object. If it has a parent,
// maintain relationship from both sides
WeblogCategoryData parent = cat.getParent();
if(parent != null) {
parent.getWeblogCategories().add(cat);
}
}
We will need to find another workaround for above if the save() call
comes for both insert and update
I suppose it's debatable which approach is cleaner, but my preference is
to maintain the current code the way it is and I think that will work
fine for any backend implementation.
One thing that I am not okay with is removing the need for a call to
XXXManager.save() for updating managed objects. The problem with doing
that is that it requires the backend implementation to use some kind of
ORM type object management solution. i.e. If I wanted to take the
current Roller code and rip out Hibernate and create my own manager
impls using raw jdbc coding then that is possible right now and it
wouldn't be if we removed calls to save() for all update action.
For your example, I think we should look more closely at the need for
maintaining the relationship on both ends, but regardless of that I
think the example may not be doing the right thing. When I want to add
a new category X to a parent category Y then I think the proper code is ...
Category X = new Category();
Y.addCategory(X); (this triggers getWeblogCategories().add(X) and
X.setParent(Y))
mgr.saveCategory(Y);
As I understand it, that is how Hibernate and other ORM solutions want
you to handle the persistence of parent/child relationships.
-- Allen
-Mitesh
-- Allen
-Mitesh
- Dave