When i have to use Hibernate's rollback - java

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.

Related

Proper Hibernate Layer Design

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());
}

Exception on transaction rollback

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.

How to catch OptimisticLockException in JPA

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

Force Hibernate To Save A Specific POJO

I have some code calling a webservice and it returns an ID. I am saving this ID in the database using hibernate. I have a filter that opens the session and commits it, rolling back when any exception occurs within the contained code. Since there is no way to get back the ID returned by the webservice I would like to save this in the database EVEN if there is an exception that occurred later on in the code. Is there anyway to do this using the same session?
It depends on who throws the exception. If it is thrown by the hibernate session object you cannot reuse the session anymore as stated in hibernate Session documentation:
If the Session throws an exception, the transaction must be rolled back and the session discarded. The internal state of the Session might not be consistent with the database after the exception occurs.
If the exception is thrown by some other code, then yes, you can do something like this:
Long yourIdFromWebservice = ...
try {
// do some processing that might result in an exception
}
catch(//the interesting exception, but not HibernateException) {
//maybe log it, rethrow it
}
finally {
session.save() //save what needed to be saved
}
or depending on your use case:
try {
// do some processing that might result in an exception
session.save() //save all stuff if no exception
}
catch(//the interesting exception, but not HibernateException) {
session.save() //save only the id from the webservice
}
The right way to do that is to use two transactions: one to save the ID, and one to save the rest of your work.
If you're using EJB, you could do the save of the ID in a bean of its own, and annotate it with a TransactionAttribute of REQUIRES_NEW.
Otherwise, you can look at what control over transactions your environment gives you, and figure out a way to have two of them.

How can I commit a Play! JPA transaction manually?

Usually, Play! commits the transaction after a request completes successfully.
What is the correct way to commit a transaction manually in Play?
void addPerson() {
Person p = new Person("John", "Doe");
p.save();
// TODO - commit the transaction
// Now p should have an ID
assert p.id != null;
usePersonIdForSomethingNasty(p.id);
}
You can get the Hibernate EntityManager by calling JPA.em(). Then, from there, you have access to the transaction (JPA.em().getTransaction()).
If you intend to manage the transaction yourself, you will want to disable Play!'s transaction handling (there is a #NoTransaction annotation you can use on the method or controller to do that). Otherwise, Play! will try to commit the transaction at the end of the request anyway, and if you have already done that yourself, that will cause an exception.
You don't need to do anything. After the request finishes without any exception, the transaction will be commited for you.
Just ensure to call "save" on all entities you want to persist at the end of transaction.

Categories