Hibernate timeout problem with servlets - java

I have a Tomcat servlet that incorporates hibernate. It works fine normally. When the servlet starts I initialize hibernate and create a session factory. I then use this session factory to generate sessions when performing various database transactions. So far so good. My problem comes after a long period of inactivity on the servlet (say when the users go home for the night and then try to log in the next morning). Suddenly, I am unable to communicate with the databse. In the logs I see
org.hibernate.exception.JDBCConectionException: Could not execute query.
If I stop and restart Tomcat, reinitializing my servlet and rebuilding my session factory, everything works fine. It is almost like the session factory itself is timing out?
Any ideas?
Thanks,
Elliott

If I stop and restart Tomcat, reinitializing my servlet and rebuilding my session factory, everything works fine. It is almost like the session factory itself is timing out?
It's not the session factory but the connections used by the session factory (e.g. MySQL is well known to timeout connections after 8 hours of inactivity by default). Either:
use a connection pool that is able to validate connections on borrow and to renew them ~or~
increase the idle timeout on the database side
OK. Suppose I use a c3P0 connection pool. How do I specify in the hibernate.cfg.xml file that I want to "validate connections on borrow" or does it do this by default?
The various options when using C3P0 are documented in Configuring Connection Testing. My advice would be to use the idleConnectionTestPeriod parameter:
The most reliable time to test
Connections is on check-out. But this
is also the most costly choice from a
client-performance perspective. Most
applications should work quite
reliably using a combination of
idleConnectionTestPeriod and
testConnectionsOnCheckIn. Both the
idle test and the check-in test are
performed asynchronously, which leads
to better performance, both perceived
and actual.
Note that for many applications, high
performance is more important than the
risk of an occasional database
exception. In its default
configuration, c3p0 does no Connection
testing at all. Setting a fairly long
idleConnectionTestPeriod, and not
testing on checkout and check-in at
all is an excellent, high-performance
approach.
To configure C3P0 with Hibernate, be sure to read the relevant instructions (and to use the appropriate properties, and the appropriate files).

Related

JMS vs Hibernate Session

My project connects to a database using hibernate, getting connections from a connection pool on JBoss. I want to replace some of the reads/writes to tables with publish/consume from queues. I built a working example that uses OracleAQ, however, I am connecting to the DB using:
AQjmsFactory.getQueueConnectionFactory followed by createQueueConnection,
then using createQueueSession to get a (JMS) QueueSession on which I can call createProducer and createConsumer.
So I know how to do what I want using a jms.QueueSession. But using hibernate, I get a hibernate.session, which doesn't have those methods.
I don't want to open a new connection every time I perform an action on a queue - which is what I am doing now in my working example. Is there a way to perform queue operations from a hibernate.session? Only with SQL queries?
I think you're confusing a JMS (message queue) session with a Hibernate (database) session. The Hibernate framework doesn't have any overlap with JMS, so it can't be used to do both things.
You'll need 2 different sessions for this to work:
A Hibernate Session (org.hibernate.Session) for DB work
A JMS Session (javax.jms.Session) to to JMS/queue work
Depending on your use case, you may also want an XA transaction manager to do a proper two-phase commit across both sessions and maintain transactional integrity.
I was also looking for some "sane" way how to use JMS connection to manipulate database data. There is not any. Dean is right, you have to use two different connections to the same data and have distributed XA transaction between them.
This solution opens a world of various problems never seen before. In real life distributed transactions can really be non-trivial. Surprisingly in some situations Oracle can detect that two connections are pointing into the same database and then two-phase commit can be bypassed - even when using XA.

Is there any performance difference between these two JDBC Connectivity?

I have used MySqlDataSource for in jdbc connectivity.I have used following code
MysqlDataSource d = new MysqlDataSource();
d.setUser("user");
d.setPassword("pass");
d.setServerName("hostname.com");
d.setDatabaseName("db");
Connection c = d.getConnection();
Also i have searched there is an option of Configuring a MySQL Datasource in Apache Tomcat.
Is there any performance difference between these two? which one is best to use?
Configuring Datasource in tomcat will help you to share same data source between applications running in same tomcat. that Datasource will be managed by container (tomcat in your case).
while the Datasource created in code will be created by your application and can be used by that application only.
So if you have multiple application running on tomcat and accessing same data source, that configuring Datasource in tomcat will be good approach and have performance factor because only one data source is created and not having separate connections for each application
But if you have only single application that the first approach you have used is good one
They both use the internally the same driver, i dont think the performance is much different here, i guess if you need to access teh database only at that place and the enduser isn't supposed to use his own authentication you may use it directly from java, but if you will need the connectivity on different places it could be helpful to configure this using apache configuration, specially that if anything changes like database server, user name or whatever you don't need to get in the code to change it, this could be very important if end users have to set their own configurations.
The improvement of configuring a pool of Connections (as the one provided by tomcat) is mainly that you will actually create and close a lot less of connections.
When using a pool, when you request a Connection to a pool it will look if it has any connection already created and available for reuse and, if it has, it will provide you with it (instead of creating a new Connection, which is a heavy operation). You must still close() a Connection provided by Tomcat so Tomcat knows that it can now reuse when it is requested again.
Additionally, the advantage of the pool is that your code does not need to know the configuration data for the Connection. He just requests a Connection from a given pool and the sysadmin configures it, allowing for greater flexibility (the sysadmin does not need to know how to configure your app, just how to configure the Tomcat which is fairly more standard).

JDBC, Hibernate and Implicit Transactions on SQL Server 2008

We're having some problems with connections getting 'stuck' on SQL Server 2008 when issued from Hibernate, running on a Glassfish instance.
Occasionally, there will be 10 or 20 calls to a stored procedure, that are all 'sleeping', and are holding open a number of transactions.
When i use DBCC INPUTBUFFER to find out more about them, it has:
Name : implicit_transaction
Does this mean that the java app, is setting 'SET IMPLICIT_TRANSACTIONS ON' as part of the batch? The only way I was able to replciate that transaction name DB side, was to use that syntax.
It appears that the java app is hanging on to the connection, but somehow losing context of the call itself, as such it never comes back to commit the transaction.
The java developers say that they are not explicitly defining any connections, and are not away that they are setting any other connection properties on purpose. The calls are all being made under the READ COMMITTED isolation level.
How can I found out whether there's some hidden attribute set, or if some hibernate setting is causing this annoying behaviour?
You can ask Hibernate to log the sql statements it's executing.
This article describes two ways to do that.
SessionFactory sf = new Configuration()
.setProperty("hibernate.show_sql", "true")
// ...
.buildSessionFactory();
or in the log4j configuration
log4j.logger.org.hibernate.SQL=DEBUG, SQL_APPENDER
log4j.additivity.org.hibernate.SQL=false

How can an Hibernate web application start if its database is not yet available

What would be the best way to setup/design or simply configure an Hibernate based Java web application to support being started (i.e. sessionfactory initialization) up if the database connectivity is not yet available, but will be, albeit at a much later time.
In other words, is there an easy way to handle out of order initialization between an Hibernate server application and its database?
As far as i know . If you use external connection pool and hibernate is no responsible to making the connections and in additional hbm2ddl is set to none than hibernate should not connect to the database untill you open a session.
Any way if it will failed to open session because there is no connection it will success to open new session as soon as there is databas connectivity.

How do you determine if a JDBC Connection was retrieved from a JTA enabled DataSource or straight JDBC?

I'm using a vendor API to obtain a JDBC connection to the application's database. The API works when running in the application server or when running in a stand-alone mode. I want to run a series of SQL statements in a single transaction. I'm fine with them occurring in the context of the JTA transaction if it exists. However, if it doesn't then I need to use the JDBC transaction demarcation methods. (Calling these methods on a JDBC connection that is participating in a JTA transaction causes a SQLException.)
So I need to be able to determine whether the Connection came from the JTA enabled DataSource or if it's just a straight JDBC connection.
Is there a straight forward way to make this determination?
Thanks!
Even if it's straight JDBC, you can have a JTA transaction enabled. Checking the autoCommit flag will NOT help in this regard. You can be in a transaction, distributed or otherwise, with autoCommit set to false. autoCommit set to true would tell you you're not in a distributed transaction but a value of false just means you won't auto-commit... it could be in any kind of transaction.
I think you're going to have to call UserTransaction.getStatus() and verify that it is not equal to Status.NoTransaction(). This would tell you if you're in a JTA transaction.
What thilo says does make sense.
Otherwise, Not sure of a straight way BUT I will give you a "hack" way
write a BAD SQL which you know will give a DB exception.
That will result in a stack trace. From the stack trace, you can find out if it is a JTA derived connection or NOT ?
You could try to check the Connection's autoCommit flag to see if it is in a transaction (regardless of where it came from).
(Apparently, see the accepted answer, this does not work too well. I am not deleting this answer because the following still stands: )
But I think you should really modify your API to depend on external transactions exclusively. If you still want to support plain JDBC, wrap it into a separate API that just starts the transaction.
Update: Just re-read your question and saw that you are not providing an API, but want to use a container-managed connection. But still, can you just mandate (as part of your application's requirements) that JTA be in effect? If not, you could provide a configuration option to fall back to manually managed transactions. For such a critical feature it seems reasonable to require the proper configuration (as opposed to try to guess what would be appropriate).

Categories

Resources