A peculiar situation
This example you gave is interesting because a HibernateException
, which is not a checked exception (that is, exception that must be handled or passed to the level above) can be triggered by a SQLException
of JDBC, which is checked , which in turn can be triggered by a IOException
, which is also checked , and can happen when the connection to the bank is lost (after it has been established, of course). However, the fact that HibernateException
is not checked disallows exception handling, which may or may not be advisable in this situation, to check below (and you will see that it needs to be handled). >
When the connection drops any of the methods beginTransaction()
, save()
or commit()
will throw 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, signaling that sessao.close()
needs to be called. But sessao.close()
, which underneath the panels calls Socket.close()
, in addition to releasing the socket (system resource) will also trigger an exception when trying to close the connection that has already been lost.
Note: According to the documentation of the Session.close()
and Session.disconnect()
methods, they only need to be called in applications that pass a persistent JDBC connection ( long- in> or long-conversation ) to Hibernate rather than letting you create a pool of them alone. If you use a pool of connections do not 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 handling because it is a normal occurrence due to the loss of network connection. So just capture this second exception and do nothing more with it, not even logarithm. The socket will be released and will no longer be a busy resource on the system, which would be a potential problem if the number of open connections is (or might be) too large. The operating system is limited in the number of sockets that can keep busy, even if disconnected.
The only problem of this second exception, besides not having to log anything, is that catch (Throwable e)
should be more specific: catch (HibernateException e)
.
First exception: skip to level above
The catch
for the first exception may or may not be necessary. In general in this situation the level above will want to handle some exception of bank failure, perhaps displaying a dialog box for the user or some other way, so instead of capturing HibernateException
and simply logging you have the option to leave this exception go to the above level directly or else capture it and throw in its place a more "high-level" exception, which does not specify that it is a Hibernate exception. You may find that HibernateException
is a specific thing of a certain persistence solution that your system must be free to exchange for others, and so you should exchange it for DaoException
(Do DAs make sense in Hibernate? a lot of it's not hehehe), or PersistenceException
or something like this (I'm giving you an example here of exception, just to stress 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
}
}
}
Conclusion
In this case, you may notice that even HibernateException
not being checked and you are not required to handle the two exceptions that were generated, it is better to treat them in some way to prevent a system resource is left busy.
On the try with resources , Session
does not implement the interface Closeable
so in that case you can not use it.