В моем приложении 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 обрабатывает мои транзакции.Но на этот раз, когда выдается исключение, новая строка откатывается из обоих источников данных, а не только из транзакционного.Это все еще не то, что я ожидал: /
Кто-нибудь видит, что я делаю неправильно?Заранее спасибо,
Питер