我正在使用Spring和Hibernate尝试更新数据库的值。在出现异常的情况下,需要将错误消息保存到表中。我面临一些错误,因为当我能够将消息保存到数据库中时,事务不会回滚。这是伪代码
@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();
}
}
通过这种方式,我无法将消息保存在relatedObject
中并回滚object
中的更改。通过进行一些更改,例如放置propagation = Propagation.REQUIRES_NEW
或propagation = Propagation.REQUIRED
,或者删除用于回滚的Excpection.类,我得到了一些其他行为,比如保存错误消息,但在出现异常时也写入object
的更改,或者回滚更改,但也不将错误消息写入relatedObject
。
我也尝试使用merge
而不是saveOrUpdate
,但没有成功。
有人能帮我写一种方法,在出现错误时回滚更改,同时将错误消息保存到数据库中吗?
谢谢。
*我没有发布实际的代码,因为这不是一个个人项目。
编辑:我的transactionManager
被配置为一个XMLbean,首先我创建了objectTableTarget
,设置了sessionFactory
属性,然后我设置了另一个beanobjectTable
,引用了我想设置为事务的方法。
<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>
将日志方法移动到单独的服务中,并用@事务性(传播=传播.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();
}
}
然后spring可以在您的方法上创建代理,错误应该写入新的事务