A peculiar situation
This example you gave is interesting because a HibernateException
, that is not a checked Exception (that is, exception that must be treated or passed on to the level above) can be triggered by a SQLException
of JDBC, which is checked, which in turn can be fired by a IOException
, which is also checked, and it can happen when the connection with the bank is lost (after it has been established, of course). But the fact of HibernateException
not to be checked clear the treatment of the exception, which may or may not be recommended in this situation, to be checked below (and you will see that it needs to be treated).
When connection drops any of the methods beginTransaction()
, save()
or commit()
will launch a HibernateException
, indicating that the connection has been lost and the resource (socket opened with the bank) needs to be released. Or, in other words, signalling that sessao.close()
needs to be called. But sessao.close()
, that beneath the rags blazes Socket.close()
, besides releasing the socket (system feature) will also trigger an exception when trying to close the connection that has already been lost.
Obs.: According to the documentation of the methods Session.close()
and Session.disconnect()
, they only need to be called in applications that pass a persistent JDBC connection (long-Session or long-Conversation) to Hibernate instead of letting him create a pool of them alone. If you use a pool of connections don’t call sessao.close()
and ignore what I say about the second exception.
Second exception: capture and then ignore
This second exception does not need to receive any special treatment because it is a normal event arising from the loss of network connection. So just capture this second exception and do nothing else with it, not even log in. The socket will be released and will no longer be a busy feature in the system, which would be a potential problem if the number of open connections is (or can be) too large. The operating system is limited in the number of sockets it can keep busy, even if disconnected.
The only problem of this second exception, besides not needing to log anything, is that the catch (Throwable e)
should be more specific: catch (HibernateException e)
.
First exception: move to the level above
Already the catch
for the first exception may or may not be necessary. In general in this situation the level above will want to treat some fault exception in the bank, perhaps by displaying a dialog box to the user or in some other way, so instead of capturing the HibernateException
and simply log in you have the option to let this exception go to the above level directly or else capture it and cast in its place a more "high level" exception, which does not specify that it is a Hibernate exception. You may think that HibernateException
is a specific thing of a certain persistence solution that your system should be free to exchange for others, and so should exchange it for a DaoException
(Do Daos make sense in Hibernate? I guess not so much heheheh), or PersistenceException
or something like that (I’m giving an example of any exception here, just to emphasize this idea):
// Resolvi tornar checked também, mas isso é opcional
public class PersistenceException extends Exception {
public PersistenceException(Throwable e) {
super(e);
}
}
public void salvar(Usuario usuario) throws PersistenceException {
Session sessao = null;
try {
sessao = HibernateUtil.getSessionFactory().openSession();
Transaction transacao = sessao.beginTransaction();
sessao.save(usuario);
transacao.commit();
} catch (HibernateException e) {
throw new PersistenceException(e);
} finally {
try{
if (sessao != null) {
sessao.close();
}
} catch (HibernateException e) {
// Não precisa fazer nada
}
}
}
Completion
In this case, you can observe that even HibernateException
not being checked and you not being required to treat the two exceptions that have been generated, it is best to treat them in some way to prevent a system resource from being left busy.
About the Try with Resources, Session
does not implement the interface Closeable
then you can’t use.
That answer might help you What Try/Catch Blocks are for and when they should be used?
– DNick