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.
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());
}
When i have to use Hibernate's rollback?
Hibernate will do rollback itself in exception case, so my rollback line just external:
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
test cl = (test) session.createCriteria(test.class)
.add(...)
.list()
.get(0); // Here's throws an exception, Hibernate was rolled back automatically.
session.getTransaction().commit();
}
catch (Exception ex)
{
session.getTransaction().rollback(); // The transaction already was rolled back. Unnecessary?
}
That's the only approach to use Hibernate's rollback which i can invent but rollback has not sense there.
So in which cases i really have to use rollback?
In case there is no exception, but you still want to roleback because you found something wrong in your program logic, that's when you can use it. Like if you are updating multiple entities and your modified one and found some anomaly in the data according to your business logic, you can call rollback.
I've read out a couple of questions here regarding the OptimisticLockException with JPA, used in an stateless session bean. It is thrown, but not where I expect it obviously.
Here is the code where I expect to get the exception:
try
{
productFacade.edit(product);
}
catch(Exception {
return "lock";
}
The productFacade is generated with NetBeans and it is an EJB with a local interface, an it implements an AbstractFacade abstract class. As far as I read, this has something to do with transactions in JPA. Because the exception is thrown after the method this code snippet is in is left, not after edit() is called. Where should I than handle the exception?
Also, I will be needing the transaction mechanism for later, because I will need to update multiple products (or none if some is locked). I've found some code examples, but this leaves me wondering how should I work with transactions?
The lock error will not be thrown until the transaction commits. So you would need to handle it outside of your SessionBean or use a container managed transaction.
Or, you could just call flush() on your JPA EntityManager, then the error will be thrown.
use save and flash and catch with Exception
try {
log.info("save data versions: " + employee.getVersion());
someRepository.saveAndFlush(employee);
} catch (Exception ex) {
log.info("catch Exception");
throw new OptimisticLockException("retry data Exception");
}
if want to use retry can add anotation #Retryable with some flagging
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.
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.