-->
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.  [ 8 posts ] 
Author Message
 Post subject: Why the HibernateException.java extends RuntimeException
PostPosted: Tue Feb 21, 2006 2:19 am 
Regular
Regular

Joined: Fri Nov 12, 2004 12:07 am
Posts: 57
Location: Beijing,China
Hibernate3.x.x


Why the HibernateException.java extends RuntimeException since version 3.x.x?

I think it is not a good choice,because you'll not be fored to throw a HibernateExcetion when you are coding with Hibernate3.x.x,for example.

The Class DAO was written by user A who isn't a careful person,the source code of DAO.java may be:

class DAO{

pubic void create(Session session,Object obj){
session.save(obj);
}

}

but not

class DAO{

pubic void create(Session session,Object obj) throws HibernateException{
session.save(obj);
}

}

The Class BO was written by user B who is stupid,the source code of BO.java is:

class BO{

public void create(Object obj){
try{
Session session=HibernateUtil.openSession();
HibernateUtil.beginTrans();
new DAO().create(session,obj);
HibernateUtil.commitTrans();
}finally{
HibernateUtil.closeSession();
}

}

but not

class BO{

public void create(Object obj){
try{
Session session=HibernateUtil.openSession();
HibernateUtil.beginTrans();
new DAO().create(session,obj);
HibernateUtil.commitTrans();
}
catch(Exception e){
HibernateUtil.rollBackTrans(); // if DAO().create() failed,the trans should be roll back.
}
finally{
HibernateUtil.closeSession();
}

}


I think if User A was forced thrown HibernateException by Hibernate3.x.x from DAO.create(),then the User B would not forgot add the following code.

catch(Exception e){
HibernateUtil.rollBackTrans(); // if DAO().create() failed,the trans should be roll back.
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 2:45 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
checkked exceptions in a *framework* is in almost all cases evil.

we learned from that mistake in Hibrenate 2 and changed it for Hibernate 3 ...the code is *much* cleaner now when you are not *forced* to always catch or throw.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 2:59 am 
Newbie

Joined: Sat Feb 18, 2006 5:30 am
Posts: 17
Its always better to check-and-rollback transaction in finally block, rather than aborting it in catch( Exception ) block, because there are Throwables, which doesn't subclass Exception.

I do agree with Hibernate team. If you catch HibernateException, you usually can do nothing meaningful, that will differ from you default exception handling strategy (usually, running in circles and shouting "unexpected internal error"). So, its better to use unchecked exception for such kind of errors.

When we were using Hibernate 2.x with checked HibernateException, there were many places with following code

Code:
catch ( HibernateException e )
{
   throw new DatabaseException( e ); // extends RuntimeException
}


Which is evil, because is looks like penalty for using framework.

Now these code blocks was gone.


Top
 Profile  
 
 Post subject: Hi,max,cryozot
PostPosted: Tue Feb 21, 2006 3:22 am 
Regular
Regular

Joined: Fri Nov 12, 2004 12:07 am
Posts: 57
Location: Beijing,China
Hi max,

Thanks for your answer.

But i still have some doubts.Would you like tell me where is the cleanness that was brought by UNCHECKED EXCEPTION Hibernate3 in my j2ee project.Though i'm developing with UNCHECKED EXCEPTION Hibernate3,i still must catch HibernateException and throws it in DAO layer for roll back transaction.May be i should change my code in BO layer from

try{
openConnection();
new DAO().create();
commitTrans();
}
catch(Exception e){
rollbackTrans();
}
finally{
closeConnection();
}

to


try{
openConnection();
new DAO().create();
commitTrans();
}
catch(RuntimeException e){ // the line was changed.
rollbackTrans();
}
finally{
closeConnection();
}


Hi,cryozot

Why you said
"Its always better to check-and-rollback transaction in finally block, rather than aborting it in catch( Exception ) block"?

if you don't catch HibernateException and throw a DataException from DAO layer,i think your code in BO layer must be:

try{
openConnection();
new DAO().create();
}
finally{
try{
commitTrans();
}
catch(RuntimeException e)}
rollbackTrans();
}
closeConnection();
}

is it really? please tell me,thank you.


Top
 Profile  
 
 Post subject: Hi,cryozot
PostPosted: Tue Feb 21, 2006 3:39 am 
Regular
Regular

Joined: Fri Nov 12, 2004 12:07 am
Posts: 57
Location: Beijing,China
Thanks a lot for your detailed answer.

With checked exception Hibernate2. The code like following:

class DAO {
public void create() throws DataException{
try{
.....
}
catch(HibernateException e){
throw new DataException(e);
}
}
}

With UNCHECKED exception Hibernate3,the code like following:

class DAO{
public void create(){
}
}

The class DAO changed to more clear and it is not required that the class DataException be defined.

is it right?


Top
 Profile  
 
 Post subject: Re: Hi,max,cryozot
PostPosted: Tue Feb 21, 2006 3:39 am 
Newbie

Joined: Sat Feb 18, 2006 5:30 am
Posts: 17
amjn wrote:
try{
openConnection();
new DAO().create();
commitTrans();
}
catch(RuntimeException e){ // the line was changed.
rollbackTrans();
}
finally{
closeConnection();
}


This code is even more dangerous, because RuntimeException is a subclass of Exception, which is subclass of Throwable. There are other throwables (Errors), which are not Exceptions. If code in your try block will throw Error, transaction won't be aborted.

amjn wrote:
try{
openConnection();
new DAO().create();
}
finally{
try{
commitTrans();
}
catch(RuntimeException e)}
rollbackTrans();
}
closeConnection();
}


This code is also wrong. You will commit your transaction even if exception is thrown in try block.

I recomend you to refresh your memories, regarding exception handling in Java, especially how finally block works.

Correct sequence it your case would be something like this:

Code:
try
{
  beginTransaction();

  // perform transactional work

  commitTransaction();
}
finally
{
  // if transaction is still active, then we have an exception
  if ( currentTransaction().isActive() )
  {
    rollbackTransaction();
  }
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 09, 2006 12:48 pm 
Newbie

Joined: Tue Mar 09, 2004 11:17 pm
Posts: 8
With checked exception Hibernate2. The code like following:
Code:

class DAO {
  public void create() throws DataException{
    try{
     .....
    }
    catch(HibernateException e){
    throw new DataException(e);
    }
  }
}

With UNCHECKED exception Hibernate3,the code like following:
Code:
class DAO{
  public void create(){
  }
}

This is correct indeed, and many will be very happy with it, IMHO it has a problem. HibernateException will bubble up to upper layers of your application, where you probably don't want to know anything about Hibernate. That's why I still keep catching and replacing HibernateException with my own exceptions.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 09, 2006 11:32 pm 
Newbie

Joined: Sat Feb 18, 2006 5:30 am
Posts: 17
Lovecraft wrote:
With checked exception Hibernate2. The code like
This is correct indeed, and many will be very happy with it, IMHO it has a problem. HibernateException will bubble up to upper layers of your application, where you probably don't want to know anything about Hibernate. That's why I still keep catching and replacing HibernateException with my own exceptions.


It usually not an issue, because "upper layers" of application is neither aware of persistence nor capable to recover from such errors other than write "unexpected error" to log, rollback transaction, and continue. In that case HibernateException and DataException both contains have same meaning, but rethrowing HibernateExcepion makes code more messy.

BTW, if you use lazy-loading, it is impossible anyway to wrap all HibernateException, because they might occur almost anywhere.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.