如何以编程方式在线程中获取事务管理器?

11

我有一个Wicket页面,其中包含两个由Spring管理的bean,一个是DAO,另一个是Service对象:

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)更新数据库中的一行数据。
但是数据没有被更新到数据库中,我认为这是因为DAO没有包装在@Transaction或tx:adviceaop标签中。
我想知道是否有一种编程方式可以获取事务管理器,并手动打开/关闭事务?
注意:我可以通过在spring的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的保存/更新/删除操作将像魔术般顺利进行。

但我不想添加此配置。因为实际上,DAO扩展了AbstractDao,还有其他DB / DAOs也扩展了此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

因此,如果此AbstractDAO的CRUD由transactionManagerApp建议,其他DAO可能会出现问题,因为其他DAO可能依赖于txManagerForum、txManagerBank、txManagerUser等。
回到问题上来,有没有一种编程方式可以获取txManager?例如:
TransactionManager txManager = TxManagerThreadLocal.get();
txManager.begin();
ma.setNewEmailSentTime(null);
mergeAccoungDao.update(ma); 
txManager.commit();

或者有更好的方式来封装DAO事务吗?非常感谢。
1个回答

16

您需要将事务管理器注入到您想使用它的类中。您可以使用构造函数或基于属性的注入,也可以使用自动装配。

一旦您获取了事务管理器,您就可以使用Spring中的编程式事务支持来启动和提交事务。以下是来自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();
      }
    });
  }
}

请参考参考资料了解更多细节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接