Spring Transaction - автоматический откат предыдущих обновлений БД при сбое одного БД - PullRequest
5 голосов
/ 07 октября 2010

Я пишу простое приложение (Spring + Hibernate + PostgreSql db).Я просто пытаюсь создать образец объекта и сохранить в БД.

Я запускаю простой основной метод класса Java, где я загрузил applicationContext и получил ссылку на класс обслуживания, как показано ниже

TestService srv = (TestService)factory.getBean("testService");  

Контекст приложения - контекст:

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactoryVsm" />
</bean>

<bean id="testService" class="com.test.service.TestServiceImpl">
    <property name="testDao" ref="testDao"/>
</bean>

<bean id="testDao" class="com.test.dao.TestDaoImpl>
    <property name="sessionFactory" ref="sessionFactoryVsm"/>
</bean>

В TestService я ввел TestDao.В тестовом сервисном методе я создал для сотрудников объекты emp1 и emp2 и дважды вызываю dao для обновления.

Код TestDaoImpl:

public void saveOrUpdate(BaseDomainModel baseObject) {

    Session session = null;
    try {
        session = getHibernateTemplate().getSessionFactory().openSession();
        session.saveOrUpdate(baseObject);
        session.flush();
    } catch (Exception e) {
        logger.error("Generic DAO:saveOrUpdate::" + e);
        e.printStackTrace();
    } finally {
        if (session != null) {
            session.close();
        }
    }

}

При сбое обновления emp2 emp1 также должен завершиться ошибкой.Как я это сделал.Пожалуйста, совет

Заранее спасибо

Обновлено:

Спасибо, Нанда.Я попробовал декларативную транзакцию.Но это не работает.emp1 сохраняется и не откатывается второй вызов дао eveb завершается неудачно.Я добавил в метод рекомендации по транзакциям.

, чтобы проверить, применяется ли рекомендация по транзакциям или нет, я изменил распространение на "NOT_SUPPORTED".но emp1 сохраняется.ожидается, что мы должны получить исключение типа транзакции не поддерживается.пожалуйста, совет.

ОБНОВЛЕНО

@ seanizer - Спасибо за обновление.Я даже пытался добавить
@Transactional (распространение = Propagation.NOT_SUPPORTED) public void saveEmp (Employee emp) к этому методу обслуживания.Но это не сработало.Более того, повторение коллекции остается в силе, только если мне нужно вызвать одного дао.Если в случае, если мне нужно вызвать два разных дао, чтобы сохранить obj1 и obj2 - это может не помочь.Просто чтобы проверить, применяется ли транзакция, я получаю @Transactional (распространение = Propagation.NOT_SUPPORTED).Но все же obj1 сохранился.Я просто сомневаюсь в правильности приведенной конфигурации / аннотации xml.пожалуйста, проверьте

<bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactoryVsm" />
    </bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
         <tx:method name="saveEmp" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="*"/>
    </tx:attributes>
 </tx:advice>   
 <aop:config>
    <aop:pointcut id="testServiceOperation" expression="execution(*com.test.service.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceOperation"/>
  </aop:config> 

Я использую org.springframework.orm.hibernate3.HibernateTransactionManager для TransactionsManager.Это правильно?


Обновлено

Я создал класс исключений myRuntimeExp, расширяющийся от RuntimeException и выбрасывающий его из метода Dao в метод service.но пока отката не происходит.Я просто сомневаюсь, правильно ли я дал конфигурации в applnContext.xml.Может ли кто-нибудь помочь мне, как проверить, применяется ли к методу рекомендация по транзакции или нет?Есть ли способ запустить его в режиме отладки и проверить

Проблема:

Я использовал

session = getHibernateTemplate().getSessionFactory().openSession();

Но это должен быть текущий сеанс, и он работает нормально.

session = getHibernateTemplate().getSessionFactory().getCurrentSession();

Ответы [ 5 ]

4 голосов
/ 07 октября 2010

Если вы используете декларативное управление транзакциями, вы можете потерять большую часть этого шаблона:

TestDaoImpl:

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory f){
    this.sessionFactory = f;
}

public void saveOrUpdate(BaseDomainModel baseObject) {
    Session session = sessionFactory.getCurrentSession();
    session.saveOrUpdate(baseObject);
}

И вы можете контролировать обработку транзакций изуровень обслуживания с использованием @Transactional (или конфигурации XML)

TestServiceImpl:

private TestDao testDao;

public void setTestDao(TestDao  d){
    this.testDao = d;
}

@Transactional // one transaction for multiple operations
public void someServiceMethod(Collection<BaseDomainModel> data){
     for(BaseDomainModel baseObject : data)
         testDao.saveOrUpdate(baseObject);
}

Ссылка:

4 голосов
/ 07 октября 2010

По умолчанию Spring откатывается только для непроверенного исключения. Вы должны предоставить атрибут rollback-for и указать, какое исключение вы пытаетесь перехватить.


Из источника Документация :

Однако обратите внимание, что транзакция Spring Framework По умолчанию инфраструктурный код только помечает транзакцию для откат в случае выполнения, непроверенные исключения; то есть когда выброшенное исключение является экземпляром или подклассом RuntimeException . ( Ошибки также - по умолчанию - приводят к откату.) Проверено исключения, которые вызываются из транзакционного метода, будут не результатом в откатываемой транзакции.

2 голосов
/ 07 октября 2010

Вот, возьмите эти отрывки и надеемся, что они вам помогут:

<bean id="abstractService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
    <props>
        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>
        <prop key="update*">PROPAGATION_REQUIRED, -Exception</prop>
        <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>
        <prop key="delete*">PROPAGATION_REQUIRED, -Exception</prop>
        <prop key="save*">PROPAGATION_REQUIRED, -Exception</prop>
    </props>
</property>
</bean>

<bean id="persistenceServiceTarget" class="com.blahblah.server.service.impl.PersistenceServiceImpl">
<property name="persistenceDAO" ref="persistenceDAO" />
</bean>
<bean id="persistenceService" parent="abstractService">
     <property name="target" ref="persistenceServiceTarget" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="abstractDAO"
class="org.springframework.orm.hibernate3.support.HibernateDaoSupport"
abstract="true">
<property name="sessionFactory">
    <ref bean="webSessionFactory" />
</property>
</bean>

<bean id="persistenceDAO" class="com.blahblah.server.dao.impl.PersistenceDAOImpl"
parent="abstractDAO">
</bean>

Это должно быть то, что вам нужно.Они не обязательно должны быть в одном файле, может быть, они разделены между сервисами и даосами.

1 голос
/ 29 июля 2011

другой пункт - проверить, поддерживает ли база данных транзакцию

1 голос
/ 07 октября 2010

Вы можете поместить sessionFactory в TestServiceImpl и открыть там сессию.

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