Как программно получить менеджер транзакций в потоке?

У меня есть страница калитки, которая содержит два управляемых компонента 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();

Или есть ли какой-либо лучший способ перенести транзакцию к ДАО?

Большое спасибо.

11
задан Sean Patrick Floyd 2 July 2010 в 16:24
поделиться

1 ответ

Вы должны внедрить диспетчер транзакций в класс, который хотите его использовать. Для этого можно использовать конструктор или внедрение на основе свойств или использовать автоматическое подключение. Получив менеджер транзакций, вы можете использовать программную поддержку транзакций в 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();
      }
    });
  }
}

См. ссылку для получения дополнительных сведений.

15
ответ дан 3 December 2019 в 08:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: