Как откатить операцию транзакционной базы данных и сохранить сообщение об ошибке в другой таблице? - PullRequest
1 голос
/ 04 августа 2020

Я использую 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.class для отката, я получаю некоторые другие варианты поведения, например, сохраняю сообщение об ошибке, но также записываю изменения object, когда возникает исключение. , или откатить изменения, но не записать сообщение об ошибке в relatedObject.

Я также пробовал с merge вместо saveOrUpdate, но безуспешно.

Может кто-нибудь помогите мне написать способ отката изменений в случае ошибки, но также сохранить сообщение об ошибке в базе данных?

Спасибо.

* Я не публикую фактический код, потому что это не личный проект.

РЕДАКТИРОВАТЬ: Мой transactionManager настроен как XML bean, где сначала я создаю objectTableTarget, устанавливая свойство sessionFactory, а ниже я устанавливаю другой bean objectTable, ссылаясь на методы, которые я хочу сделать транзакционными.

<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>

1 Ответ

1 голос
/ 04 августа 2020

переместите свой метод журнала в отдельный сервис и аннотируйте его с помощью @Transactional (ropagation = 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();
        }
}

Затем spring может создать прокси для вашего метода, и ошибка должна быть записана в новой транзакции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...