У меня есть две базы данных с двумя наборами конфигураций пружин: нижний уровень - CORE
дБ, верхний уровень - APP
дБ.
У каждого БД есть свой persistenceUnit, entityManagerFactory, TransactionsManager, с добавленным именем БД, например, "entityManagerFactoryApp", "TransactionsManagerCore" ...
Теперь у меня есть класс Service, заключающий в себе некоторыеDAO в APP, а некоторые в CORE.Но я обнаружил, что не могу зафиксировать DAO в CORE в моем тесте:
Вот мой класс обслуживания:
@Inject private AppDao appDao;
@Inject private CoreDao coreDao;
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
coreDao.save(...); //failed !
}
И это мой тестовый класс:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManagerApp" , defaultRollback=false)
public class ServiceTest
{
@Inject private Service service;
@Test
@Transactional
public void testSomeMethod()
{
service.someMethod(...);
}
}
Iзнаю причину, по которой я не могу зафиксировать DAO в CORE, потому что @TransactionConfiguration тестового класса имеет значение "transactionManagerApp
", а не "transactionManagerCore
".Таким образом, любые действия CREATE / UPDATE / DELETE в DAO CORE не будут совершены.Но я не могу включить два txManager одновременно (есть ли способ?) .
Итак, я изменяю свой класс обслуживания:
@Inject
@Qualifier("entityManagerFactoryCore")
private EntityManagerFactory emfCore;
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
Session session = (Session) EntityManagerFactoryUtils.getTransactionalEntityManager(emfCore).getDelegate();
Transaction tx = session.beginTransaction();
coreDao.save(...); //success
tx.commit();
}
Да, это работает!Но это НЕ то, что я хочу!Потому что он вводит много избыточных кодов (session, tx, commit ...).
И ... есть еще один способ удалить session / EntityManagerFactoryUtils из Service и переместить их в тестовый класс:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:app.xml"})
@TransactionConfiguration(transactionManager="transactionManagerApp" , defaultRollback=false)
public class ServiceTest
{
@Inject private Service service;
@Inject
@Qualifier("entityManagerFactoryCore")
private EntityManagerFactory emfCore;
@Test
@Transactional
public void testSomeMethod()
{
Session session = (Session) EntityManagerFactoryUtils.getTransactionalEntityManager(emfCore).getDelegate();
Transaction tx = session.beginTransaction();
service.someMethod(...);
tx.commit();
}
}
это тоже работает, но тоже ужасно!
Теперь мой вопрос, есть ли у Spring способ автоматически открыть связанные транзакции и менеджер транзакций иначало / конец tx?
PS: я заметил это: 10.5.6.2 Менеджеры множественных транзакций с @ Transactional , но это, кажется, не выполняет мое требование: открыть другой txManager в методе ONE
.
Среды: spring-3.0.5, hibernate-3.6.0, JPA2
- обновлено -
Спасибо @Bozho за сообщение о вызове нового @Транзакционный (value = "txMgrName") метод, который я пробовал, но все равно не удался:
Вот мой код службы:
@Override
@Transactional
public void someMethod(foo bar)
{
appDao.save(...); //success
someCoreMethod();
}
@Transactional(value="transactionManagerCore" , propagation=Propagation.REQUIRES_NEW)
private void someCoreMethod(...)
{
coreDao.save(...); //failed
}
в core.xml:
<bean id="transactionManagerCore" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryCore" />
<qualifier value="transactionManagerCore"/>
</bean>
Всё равно не получилось, coreDao всё равно ничего не экономит.Я думаю, может быть, это потому, что метод является частным и не перехвачен Spring.Поэтому я извлекаю метод на уровень интерфейса / реализации:
Service (interface)
public void someMethod(foo bar)
public void someCoreMethod(...)
ServiceImpl (class) : unchanged
Но все равно не получилось!Фактически, я обнаружил, что spring пропускает аннотацию @Transactional в someCoreMethod ().
Я даже могу аннотировать @Transactional (value = " non-creation-txManager-name") с НЕПРАВИЛЬНЫМ txManager, и Spring не сообщает об ошибке (и ничего не фиксирует)!
Я что-то пропустил?