У меня есть страница калитки, которая содержит два управляемых компонента Spring, каждый - ДАО, другой - Объект службы:
public class MergeAccountsPage extends WebPage
{
@SpringBean
private MergeEmailDao mergeEmailDao;
@SpringBean
private MergingService mergingService;
}
MergingService
методы реализации главным образом аннотируются @Transactional
, так каждое вовлечение действия MergingService хорошо работает.
Но проблема возникает сюда:
Link<Void> link = new Link<Void>("cancelLink") {
@Override
public void onClick() {
ma.setNewEmail(null);
ma.setNewEmailClicked(null);
ma.setNewEmailSentTime(null);
mergeAccoungDao.update(ma); //not written to DB
setResponsePage(...);
}
};
Ссылка будет звонить mergeAccoungDao.update(ma)
обновить строку в DB.
Но данные не обновляются к DB, я думаю, что это - потому что ДАО не перенесен в @Transaction, ни tx:advice
и aop
теги.
Интересно там способ программно получить менеджер транзакций и вручную открыться/закрыть транзакцию?
Примечание: Я могу решить проблему путем добавления этого кода в XML пружины:
<tx:advice id="txAdviceApp" transaction-manager="transactionManagerApp">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="methods" expression="execution(* destiny.utils.AbstractDao+.*(..))"/>
<aop:advisor advice-ref="txAdviceApp" pointcut-ref="methods"/>
</aop:config>
Так, чтобы ДАО сохранил/обновил/удалил, будет работать как очарование.
Но я не хотел бы добавлять эту конфигурацию. Поскольку на самом деле, ДАО расширяет AbstractDao, и существует другой DB/дао, расширяют этот AbstractDao:
public interface AbstractDao<T> {
public T get(Serializable id);
public T save(T t);
public T update(T t);
public void delete(T t);
}
public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T>
public interface MergeAccountDao extends AbstractDao<MergeAccount>
@Repository
public class MergeAccountDaoImpl extends AbstractDaoJpaImpl<MergeAccount> implements MergeAccountDao
Поэтому, если CRUD этого AbstractDAO является "adviced" этим transactionManagerApp, другие ДАО могут иметь проблему, потому что другие ДАО могут зависеть от txManagerForum, txManagerBank, txManagerUser... и т.д.
Назад к проблеме, существует ли способ программно получить txManager? Такой как:
TransactionManager txManager = TxManagerThreadLocal.get();
txManager.begin();
ma.setNewEmailSentTime(null);
mergeAccoungDao.update(ma);
txManager.commit();
Или есть ли какой-либо лучший способ перенести транзакцию к ДАО?
Большое спасибо.
Вы должны внедрить диспетчер транзакций в класс, который хотите его использовать. Для этого можно использовать конструктор или внедрение на основе свойств или использовать автоматическое подключение. Получив менеджер транзакций, вы можете использовать программную поддержку транзакций в Spring для запуска и фиксации транзакции. Вот пример кода из Spring reference 2.5:
public class SimpleService implements Service {
// single TransactionTemplate shared amongst all methods in this instance
private final TransactionTemplate transactionTemplate;
// use constructor-injection to supply the PlatformTransactionManager
public SimpleService(PlatformTransactionManager transactionManager) {
Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
public Object someServiceMethod() {
return transactionTemplate.execute(new TransactionCallback() {
// the code in this method executes in a transactional context
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
}
});
}
}
См. ссылку для получения дополнительных сведений.