Reputation: 305
I'm using Spring and Hibernate trying to update a value of the database. It is needed that, in case of exceptions, save the error message into a table. I'm facing some errors because when I'm able to save the message into the database, the transaction doesn't rollback. Here is the pseudo-code
@Transactional
public class ObjectTable(){
//instanciate other objects
RelatedObject relatedObject = relatedObjectController.getObjectById(primaryKey)
Object object = objectController.getObjectByRelatedObject(relatedObject.getPrimaryKey())
@Transactional(rollbackFor = Exception.class)
public updateObject(Object object) throws MyCustomException{
try{
getHibernateTemplate().getSessionFactory.getCurrentSession().evict(object);
getHibernateTemplate().getSessionFactory.getCurrentSession().saveOrUpdate(object);
getSession.flush();
}catch(Exception ex){
saveErrorMessageIntoDatabase(ex.getMessage, this.relatedObject);
throw new MyCustomException(ex.getMessage)
}
}
public saveErrorMessageIntoDatabase(String message, RelatedObject relatedObject){
relatedObject.setErrorMessage(message);
getHibernateTemplate().getSessionFactory.getCurrentSession().evict(relatedObject);
getHibernateTemplate().getSessionFactory.getCurrentSession().saveOrUpdate(relatedObject);
getSession.flush();
}
}
With this kind of tought, I'm not being able to save the message in relatedObject
and rollback the changes in object
. Making a few variations, such as putting a propagation = Propagation.REQUIRES_NEW
or propagation = Propagation.REQUIRED
or removing the Excpection.class for rollback, I get some other behaviours, like save the error message but also writes the changes of object
when there is an exception, or rollin back the changes but also not writing the error message into relatedObject
.
I also tried with merge
instead of saveOrUpdate
, but with no success.
Could someone help me write a way to rollback changes in case of error but also save the error message into the database?
Thank you.
*I don't post the actual code because this is not a personal project.
EDIT:
My transactionManager
is configured as a XML bean where first I create the objectTableTarget
setting the sessionFactory
property and bellow that I set another bean objectTable
refering to the methods I want to set as transactional.
<bean id="objectTableTarget" class="br.com.classes.ObjectTable" singleton="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="objectTable" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="objectTableTarget" />
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
<prop key="updateObject*">PROPAGATION_REQUIRED,-br.com.package.exception.MyCustomException</prop>
</props>
</property>
</bean>
Upvotes: 1
Views: 835
Reputation: 961
move your log method into separate service and annotate it with @Transactional(propagation = Propagation.REQUIRES_NEW)
@Service
public class ErrorLoggerService(){
@Transactional(propagation = Propagation.REQUIRES_NEW)
public saveErrorMessageIntoDatabase(String message, RelatedObject relatedObject){
relatedObject.setErrorMessage(message);
getHibernateTemplate().getSessionFactory.getCurrentSession().evict(relatedObject);
getHibernateTemplate().getSessionFactory.getCurrentSession().saveOrUpdate(relatedObject);
getSession.flush();
}
}
Then spring can create proxy on your method and error should be write in new transaction
Upvotes: 1