Вопрос:
Я только что провел прошлый день, занимаясь именно этим вопросом: Почему транзакции между источниками данных работают с одним диспетчером транзакций гибернации?
Как и вы, я также читал в нескольких местах, что мне нужно было использовать JtaTransactionManager ... и оказывается, что они были правы!Я объясню:
Конфигурация:
Как и вы, я начал с 2 источников данных, 2 фабрик сессий и 1 HibernateTransactionManager.
Мой тестовый код также выглядел оченьпохож на ваш, и я мог бы успешно сохранять объекты в обеих базах данных.Если бы я вручную выдал исключение, ни одно из сохранений не появилось бы в базе данных.Так что казалось, что оба откатывались правильно.Однако, когда я включил ведение журнала отладки hibernate, я увидел, что ни одно сохранение не было отправлено в базы данных, поэтому откатывать было нечего .
Проблема в тесте, поэтому я изменю ваш тест, чтобы доказать, что менеджер отдельных транзакций фактически не работает!
Требуемое изменение было предложено Дж. Б. Низетом 2 января:
Пробовали ли вы вызывать flush в обоих сеансах, прежде чем выдать исключение?
Лучший тест:
Сначала добавьте функцию flush для каждого из ваших DAO.Вот как выглядит мой:
public void flush() {
sessionFactory.getCurrentSession().flush();
}
Ваш, вероятно, будет выглядеть так:
public void flush() {
getHibernateTemplate().flush();
}
Теперь измените ваш тест так, чтобы сбрасывать каждый дао перед исключением:
@Transactional("txManager")
public class DaoHolder {
@Transactional(value="txManager", readOnly=false, propagation=Propagation.REQUIRES_NEW, rollbackFor={Exception.class})
private void runTransactionalMethod() throws Exception {
dao1.insertRow();
dao2.insertRow();
dao1.flush();
dao2.flush();
throw new Exception();
}
//...
}
Результат:
Откат выполняется только для источника данных, связанного с txManager. Это имеет смысл, поскольку txManager не знает о другом источнике данных.
Резюме:
В моем случае мне не нужно обращаться к 2 базам данных за одну транзакцию, отдельные транзакции - это нормально.Поэтому я просто определил второй диспетчер транзакций:
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2"/>
</bean>
и ссылался на это по имени в аннотации транзакций, где бы я ни обращался ко второй базе данных:
@Transactional(value="txManager2"...)
IТеперь я могу получать аннотированные транзакции для моей второй базы данных, но я все еще не могу получать транзакции в обеих базах данных ... кажется, что для этого вам понадобится JtaTransactionManager .