Spring + Hibernate: совместное использование транзакционных и нетранзакционных источников данных - PullRequest
2 голосов
/ 28 декабря 2011

В моем приложении Spring 2.5.6 + Hibernate мне нужно читать / записывать данные в / из нескольких баз данных с разными схемами.Приложение находится на Tomcat, поэтому в настоящее время я предпочитаю не использовать JTA, чтобы мне не пришлось мигрировать на полноценный сервер приложений.

Поэтому я решил простоодин транзакционный источник данных.Я могу жить с другими, не будучи транзакционными.

Но почему-то я не могу заставить его работать.Не могли бы вы взглянуть на меня, чтобы понять, что я могу делать неправильно?

Это мое applicationContext.xml:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!-- ..configuration.. -->
</bean>

<bean id="nonTransactionalSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="nonTransactionalDataSource" />
    <!-- ..configuration.. -->
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- ..configuration.. -->
</bean>

<bean id="nonTransactionalDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- ..configuration.. -->
</bean>

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

<bean id="daoHolder" class="com.app.services.TransactionTest$DaoHolder"/>

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

<bean id="transactionalDao" class="com.app.services.TransactionalDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="nonTransactionalDao" class="com.app.services.NonTransactionalDaoImpl">
        <property name="sessionFactory" ref="nonTransactionalSessionFactory" />
</bean>

Как вы можете видеть выше, это простоопределение двух сессионных фабрик, каждая из которых использует свой собственный источник данных.Менеджер транзакций использует только одну из этих фабрик сеансов, и управление tx-управлением на основе аннотаций настроено.

Вот мой модульный тест, в котором я пытаюсь проверить поведение транзакций:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/applicationContext.xml"})
public class TransactionTest {

@Autowired
private DaoHolder daoHolder;

@Test
public void testTransactions() throws Exception {

    try {
        daoHolder.runTransactionalMethod();
    } catch (Exception exception) {
        System.out.println("Exception caught");
    }
}

public static class DaoHolder {

    @Autowired
    private TransactionalDao transactionalDao;
    @Autowired
    private NonTransactionalDao nonTransactionalDao;

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor={Exception.class})
    private void runTransactionalMethod() throws Exception {
        transactionalDao.insertRow();
        nonTransactionalDao.insertRow();
        throw new Exception();
    }

}

В результате вышеприведенного теста я ожидаю, что новая строка будет вставлена ​​в нетранзакционный источник данных, потому что изменения в транзакционном источнике данных должны откатываться, потому что возникло исключение.Однако после прохождения этого теста я вижу строки, вставленные в оба источника данных.

РЕДАКТИРОВАТЬ: Я продвинулся немного дальше.Я превратил DaoHolder в интерфейс, переместил вышеупомянутую логику в класс, реализующий интерфейс (DaoHolderImpl), и пометил также класс (не только метод) с помощью @Transactional.Я также добавил этот класс как Spring Bean.Так что теперь Spring обрабатывает мои транзакции.Но на этот раз, когда выдается исключение, новая строка откатывается из обоих источников данных, а не только из транзакционного.Это все еще не то, что я ожидал: /

Кто-нибудь видит, что я делаю неправильно?Заранее спасибо,

Питер

1 Ответ

1 голос
/ 28 декабря 2011

Как насчет размещения точек останова в строке «выбросить исключение», чтобы вы могли видеть, есть ли в этой строке одна или обе базы данных?

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

Вы бы предпочли включить журналирование Spring / Hibernate, чтобы увидеть, что происходит ссделки ...

...