I've got jsp webapp on my VPS host with tomcat 7 as server. I'm using Hibernate 3 and PostgreSQL. All methods in my class DBManager (responsible for db services, connection, queries) use almost the same structure:
Session session = sessionFactory.openSession();
session.beginTransaction();
=======
HERE HQL QUERY/session.get/update/save etc are executed
=======
session.getTransaction().commit();
session.close();
The problem is that my VPS after some time (using my webapp) shows many idle postgres processes which causes server overloading and e.x VPS kills Java or refuses connection to DB. What can I do to remove the problem? Is this a problem caused by my code or something else?
You need to place session.close() in try/finally block:
try {
session.beginTransaction();
=======
HERE HQL QUERY/session.get/update/save etc are executed
=======
session.getTransaction().commit();
} catch (SQLException sqle) {
// handle the exception, e.g. session.getTransaction().rollback();
} finally {
session.close(); // this will require another try/catch
}
If exception happens somewhere in your code, the session doesn't get closed and leaks resources.
Problem solved. What I did wrong was creating new factory in each instance of class. Now I added static reference everywhere and it is working pretty good.
Related
Im developing a java web application using hibernate and I came across a basic problem:
Given user A triggers some Hibernate transaction. Start transaction, load, commit transaction.
At the same time, user B triggers a similar transaction. Then, the will get an exception: nested transactions not supported.
It seems that no more than one transaction can be active at one time.
I researched for a solution and found a lot of overview explainations like transaction-per-session pattern, but nothing tangible.
So my question is: What is a proper and simple way to handle hibernate transactions for multiple concurrent users?
the transaction management is quite standard, just remember any exceptions thrown by Hibernate are fatal , you have to roll back the transaction and close the current session immediately.
You have to close the each and every transaction.
Session session = null;
Transaction t = null;
try{
session = HibernateUtil.getSessionFactory().openSession();
t = session.beginTransaction();
//do what ever you want(session);
t.commit();
}catch(RuntimeException e){
System.out.println(e.getMessage());
}
I am working on Spring MVC + Mysql using JDBC (Non Hibernate). In project we have many services which does the CRUD work. for each method we have to do some steps like
open Connection
Rollback on error
Close connection in finally
Many developers are working on the same project and its very hard to check if connection is closed in finally by every one or not.
So is their any way where after completion of method connection get closed. can i write any class which check if execution of current method is done then close the connection.
Update
Or can we develop some class from which each developer have to ask for Connection will do work on the connection object the at the finally every one have to pass that object to destroyer. If destroyer is not called the show compile time error on that method.
Something like:
someMethod()
{
Connection connection=null
try
{
Connection connection =icrudOperation.getConnection();
//do work with connection object like preparedStatement etc.
}
catch (Exception e)
{
//logging
}
finally
{
icrudOperation.destroy(connection); // if this is not written by any one then at compile time error will shown for this method.
}
}
You shouldn't be messing with the connection in the first place. Use a JdbcTemplate to do the querying. If you really want to do stuff with the connection use a ConnectionCallback. Complete this with springs declarative transaction management and you have 1 problem less to solve.
If you really want to work with the Connection and refuse to use use the common approach of the JdbcTemplate you could fix this with Springs declarative transaction management. Wrap the datasource in a TransactionAwareDataSourceProxy. Then configure Spring to manage the transaction, this will ensure that during the transaction a single connection will be used and spring will close the connection at the end of the transaction.
I would however strongly suggest to move to the usage of the JdbcTemplate as that will make your life a whole lot easier and allows you to solve the actual business problems
One other thing your service layer shouldn't be involved in JDBC coding that should be in a data access layer which is used by the service layer.
The following should work:
try{
Connecition.close();
}
finally{
System.err.println();
Connection.close();
}
I have a question about this Hibernate samples. I didn't found an answer in Hibernate docs or in Manning Persistence with JPA. May be someone can explain what happens when I use plain JDBC.
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
// Transaction actions
tx.commit();
}
catch (RuntimeException ex) {
try {
tx.rollback();
}
catch (RuntimeException rbEx) {
log.error("Couldn’t roll back transaction", rbEx);
}
throw ex;
}
finally {
session.close();
}
My question is what will happen if transaction rollback method throw an exception? Will some transaction data be stored in database? How can I handle this exception?
My question is what will happen if transaction rollback method throw an exception?
It depends on what the exception is.
Will some transaction data be stored in database?
Unspecified. One would hope that the database will be able to recover to a point corresponding to the start of the transaction. However, there are scenarios where even that may not be possible; e.g. if you lost a disc drive, and you don't have a hot standby.
How can I handle this exception?
In general, you can't. If you get an exception and have no idea what it means or what caused it, the only sensible thing you can do (in a typical database application) is to shut the application down and get a human being to investigate the problem.
I'm working on an existing project that's configured for distributed transaction.
The project is using Hibernate but for some historical reasons, the part on which I'm working on uses JDBC and needs to stay that way.
To get a connection I have to call an API which gives me back the JDBC connection of the hibernate session.
I need to wrap up some updates/inserts in one transaction so here's what I'm doing :
Set autoCommit to false on my connection.
Do my inserts (prepare statements, execute query)
Call commit.
At commit, I get an SQLException because apparently it's not allowed to call commit/rollback explicitely with distributed transactions. I should state that changing the datasource configuration to non XA is not an option.
Any ideas how I might get around this ?
connexionDiff.setAutoCommit(false);
psInsertLiv = connexionDiff.prepareStatement(reqInsertLivraison);
psInsertLivHisto = connexionDiff.prepareStatement(reqInsertLivraisonHisto);
psSequence = connexionDiff.prepareStatement(reqCleLivraison);
ps = connexionDiff.prepareStatement(requeteRelivraison);
rs = ps.executeQuery();
while(rs.next()) {
rsSequence = psSequence.executeQuery();
while ( rsSequence.next() ) {
sequenceLivraison = rsSequence.getInt(1);
}
psInsertLiv.setInt(1, sequenceLivraison);
psInsertLiv.setInt(2, rs.getInt(1));
psInsertLiv.executeUpdate();
psInsertLivHisto.setInt(1, sequenceLivraison);
psInsertLivHisto.setInt(2, rs.getInt(1));
psInsertLivHisto.executeUpdate();
connexionDiff.commit();
}
} catch (SQLException ex) {
try{
connexionDiff.rollback();
}catch {
//......
}
} finally {
//.....
}
Thx
As you are using a XA connection, you surely are managing your transactions using JTA.
If it is a standalone JTA, get the UserTransaction and call begin and commit there. If it is inside an Application Server, use the transactional annotation or whatever the app server gives you to manage transactions. Look at this page to get an idea of how it is done in JavaEE 6.
If you are using Spring, you can also use the transactional annotation to wrap your code inside a transaction. Here is the relevant documentation.
The transaction management should be the same no matter if you are using Hibernate or plain JDBC. So check how it is done when it is using Hibernate in your project, and follow the same steps.
I am using hibernate and spring and I am getting this exception upon executing the following code:
Session oSession = getSession();
try
{
oSession.setFlushMode(FlushMode.COMMIT);
getHibernateTemplate().delete(oProject);
oSession.flush();
bResult = true;
}
catch (Exception e)
{
bResult = false;
logger.error(e);
}
I've read some session management regarding hibernate and I have a hunch that this code has poor session handling. What could be the reason of having two open sessions? Hibernate APIs says that the getSession() function returns either a new session object or an existing. In this case, where does it get the existing session object? and if it creates a new session object would that still be fine to process the collection involved?
Any help would be greatly appreciated. Thanks in advance! more power stackoverflow.
HibernateTemplate.delete(Object entity) will delete the object using other Session inside HibernateTemplate but you open a new Session object by your own, which is the root cause of the error. So you should try as following:
try
{
getHibernateTemplate().delete(oProject);
bResult = true;
}
catch (Exception e)
{
bResult = false;
logger.error(e);
}
Hibernate checks if there is a session already in opened for the current thread. If not, it creates a new one using the SessionFactory; otherwise it reuses the already opened session. Well you can reattach entity objects and the same goes for collections containing entity objects too.
But you have not mentioned how is Hibernate configured to handle sessions. It could be that you manually open sessions and the code you posted actually opens 2 sessions.