views:

310

answers:

3

When I configure hibernate to connect to a DB and for some reason the connection fails, I noticed that it doesnt throw any exception neither when building the factory (which is acceptable) nor when I call sessionFactory.openSession() (which is less acceptable). What is more annoying is that session.isConnected() returns true after I call sessionFactory.openSession(). (Which is totally unacceptable).

The only hint up to that moment that tells me that it hasnt connected to the DB is a WARN log entry caused by a java.sql.SQLException that it internally catches and just sends to the logger. Besides creating a pseudo transaction to force an exception is there any other way of getting the connection status? (Maybe an option in the configuration that says "dont log the failed connection attempt, but throw a hibernate exception) . I ve searched but not found anything. Thanks a lot.

+2  A: 

What connection pool are you using? Hibernate's built-in pool should not be used for anything other than simple tests.

Proxool, on the other hand, allows you to do exactly what you want: set test-before-use property to true and it will throw an exception if it can't find or create a suitable connection. You can even listen to connection events if you want.

ChssPly76
+1  A: 

As ChssPly mentions, you should not use Hibernate's built-in pool for much of anything. Another option other than Proxool (which I have not personally used, so I can not personally vouch for it) is C3P0. It definitely throws an exception while setting up the connection pool - I CAN vouch for that :) As that is the behavior I want with our application, it works perfectly for us.

aperkins
A: 

Sorry to reraise the issue but: I tried C3p0 and it is better than built-in, but as far as my problem is concerned it does absolutely nothing different than vanilla hibernate: If it cant acquire a connection, it throws an exception, Hibernate catches that exception and, again, hides it from me. By using c3p0, I still use the hibernate API, and whatever c3p0 throws, it gets sucked away by hibernate. Only way I though is to programmatically instantiate c3p0 datasource, and if exception is not thrown (this I can catch), then pass it to hibernate. But then I realized that to pass a DataSource to Hibernate, you can only do through JNDI URL, and this is not an option. So my last hope is to implement custom Connection Provider, use c3p0 inside and catch c3p0's exception's in there. Is there any other alternative?

Note that I didnt try proxool because it seems tricky to configure with hibernate, though I didnt myself give it a fair shot. Also sorry for assigning an answer before thoroughly testing.

Paralife
Let me clarify three things here: 1) exception will only be thrown if pool cannot obtain or create a working connection - it will not be thrown simply because one particular connection has failed; 2) Hibernate will not attempt to obtain a connection until it's actually needed: `openSession()` does **NOT** obtain one; 3) Hibernate will not hide connection exception; it will, however, convert it into JDBCException which is unchecked which is what you should be catching.
ChssPly76
I'm not sure why you care so much about connection failing being detected _immediately_ rather than when you actually try to do something with it; but if you do, call `openSession().connection()` which **WILL** try to obtain it and catch `JDBCException` from which you can obtain nested `SQLException` if it fails.
ChssPly76
your first comment clarified things. The only thing now that seems strange and very counter-intuitive is this: Since as you said Hibernate will not attempt to obtain connection if it doesnt need it, what is the point of having an Session.isConnected() method? Do I need to already have tried to obtain a connection in some way order to trust isConnected() 's return value? If yes, then I dont need it because I will get an exception at the attempt. It doesnt make sense...
Paralife