-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: How best to update() in a DAO?
PostPosted: Mon Feb 28, 2005 3:44 am 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
Hello,

I'm finishing up the hibernate port of our DAO classes (previously MySQL JDBC).

I'm torn regarding the best way to update() an object in a DAO - regarding transient vs persistent state. Let me paint this picture for you (I'm not a good artist)...

Our UserDAO's update(User u) method can be called in two scenarios...

[ 1 ]
User u = userDAO.findUser( "greg" );
u.setPassword("nicepassword");
userDAO.updateUser( u );

[ 2 ]
User u = getUserFromSomeFarFarAwayPlaceLikeTheClient();
userDAO.updateUser( u );

In the first scenario the updateUser() method is presented with a persistent user object, whereas in the second scenario, the updateUser() method is presented with a transient user object.

Lets keep in mind that a DAO cannot/shouldnot distinguish between these two cases - the MySQL version of our DAO really does not care - it simply creates an UPDATE SQL statement. What I mean is that I don't want to break our DAO interface and create two distinct methods (updateUserPersistent and updateUserTransient).

My reading of the documentation and the forums leads me to believe that I should not be calling hibernate's update() function for persistent objects (just for transient ones).

However - the updateUser() method seems to work correctly if I just call update() regardless of transient or persistent state.

Please inform me on how I should proceed.

I came up with a "hack" type of "solution". Assuming I'm using lazy initialization, I can detect inside the updateUser() method whether the object being stored is persistent. I do this by checking the superclass for the string "CGLIB". If it is found this indicates a persistent object, and I don't have to call hibernate's update() function.

Please let me know.

Thanks,

Mal.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 28, 2005 4:19 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
See chapter 9.4. Updating objects of the docs.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 28, 2005 4:41 am 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
Ernst,

Thanks for your reply. I noticed when checking my documentation at that chapter/section that my documentation was out of date. There is in fact more updated information in the latest copy.

However my outstanding question still stands. Since my DAO objects handle both transient and persistent objects from time-to-time (without knowing which it is at any moment), is it "safe", or "ok" for me to call update() reardless?

I believe so, but I'm hoping for verification.

Thanks,

Mal.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 3:15 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
No, use saveOrUpdate() and make sure you understand how the dirty checking works.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 3:47 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
malachii,
what do you really mean by trasient?
- fresh new instance of a persistant class created in another layer
- or detached instance, that mean that in the datastore there is a row with the given identity value

If you call update() on a detached instance this will execute a SQL UPDATE even if no property has changed (so also take a look at select-before-update to avoid this)
If you call update() on an attached instance --> it's not really clean but it isn't dangerous for you and it allos you not to change your dao interface.

Now Ernst talk about saveOrUpdate, use it if you have to manage both detached and new instance.

session.update() doesn't mean execute SQL UPDATE, it means "update my session putting this instance under its control".

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 5:12 pm 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
anthony wrote:
malachii,
what do you really mean by trasient?
- fresh new instance of a persistant class created in another layer
- or detached instance, that mean that in the datastore there is a row with the given identity value

If you call update() on a detached instance this will execute a SQL UPDATE even if no property has changed (so also take a look at select-before-update to avoid this)
If you call update() on an attached instance --> it's not really clean but it isn't dangerous for you and it allos you not to change your dao interface.

Now Ernst talk about saveOrUpdate, use it if you have to manage both detached and new instance.

session.update() doesn't mean execute SQL UPDATE, it means "update my session putting this instance under its control".


Anthony,

By transient I mean detached instances that exist in the datastore. So I think the first part of your answer (without saveOrUpdate) is correct for me.

You say it isn't very clean (and I agree), because I believe I'm not taking advantage of Hibernate's abilities in this (better to not update() if it isn't required - for a persistent instance).

How would you propose changing the standard DAO/Factory pattern to better suit hibernate's abilities in this? My DAO's noramally have getUserByXXXX, updateUser(user u), and so forth, like most DAO's. When using DAO's in business logic, you sometimes call userDAO.update(userX) on a persistent, or transient/detached instance.

I suppose I could add an updateAttached(User u), and updateDetached(User u), and I could simply implement both methods the same way in m JDBC DAO's.

Thoughts?

Thanks,

Mal.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 5:41 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
this is only my POV:
first,
i think having one DAO per entity is too much, you're always working with objet networks... so which DAOEntity is reponsible to manage the all graph?
So if your OO design is fine, if you have well designed your packages, i prefer using one DAO per package or root object and so i call my DAO: MyPackageDAO.
And if you have 2 possible root objects for a package, no problem myPackageDAO implements myRootObjectDAOInterface1 implements myRootObjectDAOInterface2 and i use the interfaces in my higher layer.

Second,
DAO means Data Access Object, in hibernate you should use it to isolate hibernate specific calls because it will be easier to reuse and maintain.
Generally it's a great place to write queries and reuse these queries. So in fact DAO should be called ORMO (joking).
You should stop thinking in SQL update, insert, delete but focus on lifecycle semantics. Your DAO should offer:
- querying
- attaching modified
- attaching unmodified(with a specific lockmode)
- persisting (making persistent)
- deleting (making transient)
- detaching (making detached)
- ...
In fact, what i use is
MyPackageDAO implements MyRootObjectDAOInterface1 implements MyRootObjectDAOInterface2 extends BaseDAOHibernate

And my BaseDAOHibernate just offer all the services except querying which is specific to my use case.

Now i don't have a DAO layer because tomorrow i may switch from hibernate to JDO (ugh too hard to say it!), when you start using hibernate, you love it and use it for your life ;).
I just do it as i said because i want to reuse my code and easily maintain it. So i don't care having methods like lock, save, update, refresh in my BaseDaoHibernate.

All my apps are using this, i'm happy because i can switch to hibernate3 very easily ;)

hope this help.

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 7:06 pm 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
anthony wrote:
this is only my POV:
You should stop thinking in SQL update, insert, delete but focus on lifecycle semantics. Your DAO should offer:
- querying
- attaching modified
- attaching unmodified(with a specific lockmode)
- persisting (making persistent)
- deleting (making transient)
- detaching (making detached)


Anthony,

This actually helps quite a bit. I have been locked into the JDBC world for a while, and so I'm paranoid about isolation - I want to make sure that NO DB specific problems leak through the DAO layer...

When you're using a tool such as hibernate which already deals with DB isolation, your data access layer doesn't need to do this anymore. You can "feel free" to expose methods in your DAO's that are in fact "hibernate specific" like lock(), and as you say, detaching, and attaching objects, which are not normally found in a typcial DAO.

I'll have to get used to the hibernate way of thinking, and not restrict myself to the strict DOA rules I was following before.

I trust this is your message :-)

As to whether to use a DAO for each object, or one for each package, or even one layer for everything is a different topic I think. This depends on the size of the project, and the number of developers sharing code in my opinion.

For the short term, I'm happy just to get hibernate "shoe-horned" into our existing DAO framework.

Thanks!

Mal.

p.s. Do you do your transaction management calls in HibernateUtil, or in your DAO base classes? I'm still trying to find my "favourite" place to do this.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 01, 2005 7:19 pm 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
Perhaps I can summarize your message in one line?

With hibernate, use DAO's to shield from the underyling data (queries, etc), rather than from the persistence mechanism (hibernate, JDO). Once I've chosen hibernate, it provides the DBMS independance that more generalized DAO's strive for anyhow. That way I can gain the performance and style advantages of hibernate (detached instances, transients, etc), and better utilize an OO style DAO API.

What do you think?

Mal.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 21, 2005 2:02 am 
Beginner
Beginner

Joined: Thu Feb 17, 2005 6:04 pm
Posts: 23
Anthony,

Sorry this thread is quite old!

Anyhow, I am hoping that you could give me a better idea of the kind of services your BaseDAOHibernate ancestor provides. Do you still use a "static util" class like HibernateUtil?

Thanks,

Mal.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.