2010-07-01 2 views
11

У меня есть страница калитку, которая содержит две пружинные-управляемых компонентов, один DAO, другой объект службы:Как программно получить менеджер транзакций в потоке?

public class MergeAccountsPage extends WebPage 
{ 
    @SpringBean 
    private MergeEmailDao mergeEmailDao; 

    @SpringBean 
    private MergingService mergingService; 
} 

методы реализации в MergingService «s в основном с аннотацией @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) обновить строку в БД.

Но данные не обновляются в БД, я думаю, это потому, что DAO не завернуты в @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> 

Так что дао экономят/обновление/удаление будет работать как шарм.

Но я не хотел бы добавлять этот конфиг. Потому что на самом деле, DAO расширяет AbstractDao, и есть другие DB/объекты DAO расширяющих этот 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 является «советовал» этот transactionManagerApp, другие объекты DAO могут иметь проблемы, потому что другие DAO могут зависеть от txManagerForum, txManagerBank, txManagerUser ... и т. Д.

Назад к проблеме, есть ли способ программно получить txManager? Такие как:

TransactionManager txManager = TxManagerThreadLocal.get(); 
txManager.begin(); 
ma.setNewEmailSentTime(null); 
mergeAccoungDao.update(ma); 
txManager.commit(); 

Или есть ли лучший способ заключить сделку в DAO?

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

ответ

14

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

Смотрите reference для более подробной информации.

+0

Спасибо, это работает! – smallufo

Смежные вопросы