繁体   English   中英

一个Spring @Transaction中的两个dao方法

[英]Two dao methods in a single Spring @Transaction

我正在使用Spring的@Transactional和Hibernate。 我试图将两个dao方法放入单个事务中,并希望在特定的Exception上回滚。 代码如下:

服务类别方法:

@Transactional(propagation=Propagation.REQUIRES_NEW,value="txManager",rollbackFor=TransactionUnSuccessException.class)
public Account makeTransaction(Transaction transaction, String userName)
        throws TransactionUnSuccessException {
    Account account = null;
    account = transferDao.makeTransaction(transaction, userName);
    return account;
}

道方法:

@Repository
public class TransferDao extends HibernateDaoSupport {
@Autowired
private SessionFactory sessionFactory;



public Account makeTransaction(Transaction transaction, String userName)
        throws TransactionUnSuccessException {
    HibernateTemplate hibernateTemplate = getHibernateTemplate();
    Account account = null;
    Session session = hibernateTemplate.getSessionFactory().openSession();
    //session.beginTransaction();
    updateSelfAccount(transaction, userName, session);
    account = updateAnotherAcccount(transaction, session);
    //session.getTransaction().commit();
    return account;
}

private void updateSelfAccount(Transaction transaction, String userName,
        Session session) {
    User currentUser = null;
    System.out.println("TransferDao.updateSelfAccount()" + transaction);

    Query query = session.createQuery("from User where userName=:userName");
    query.setParameter("userName", userName);
    currentUser = (User) query.list().get(0);

    currentUser.getAccount().getTransactions().add(transaction);
    currentUser.getAccount().setAvailableBalance(
            currentUser.getAccount().getAvailableBalance()
                    - transaction.getAmount());
    transaction.setTransAccount(currentUser.getAccount());
    session.save(transaction);
    session.update(currentUser.getAccount());
    session.update(currentUser);


private Account updateAnotherAcccount(Transaction transaction,
        Session session) throws TransactionUnSuccessException {

       Account account = null;
    try {
        Query query = session
                .createQuery("from Account where accNo=:accNo");
        query.setParameter("accNo", transaction.getToAcc());
        account = (Account) query.list().get(0);
        if (account.getAvailableBalance() < 5000) {
            account.setAvailableBalance(account.getAvailableBalance()
                    + transaction.getAmount());
            account.getTransactions().add(transaction);
            transaction.setTransAccount(account);
            session.save(transaction);
            session.update(account);
        } else {
            throw new TransactionUnSuccessException();
        }
    } catch (TransactionUnSuccessException te) {
        te.printStackTrace();
    }

    return account;
}
}
}

XML配置:

<tx:annotation-driven transaction-manager="txManager"/>
   <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
   </bean>

如果两个方法(updateSelfAccount,updateAnotherAcccount)中的任何一个失败,则应该回滚整个事务。 但是,即使我不确定这是否在单个事务中全部发生,它也无法回滚给定的异常。 请纠正我。

使用@Transactional批注的目标是您的代码不应处理事务本身。 在您的代码示例中,您使用@Transactional,因此您不必做类似的事情

session.beginTransaction();

您是否使用其他方法正确设置了spring

<bean id="txManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="datasource" ref="dataSource"
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

通常,sessionFactory在dao中为@Autowired,以便轻松访问您执行的会话

sessionFactory.getCurrentSession()

最后一点,您不需要费劲尝试,然后抛出TransactionUnSuccessException,默认情况下,事务将在发生任何异常时回滚。

对于初学者,请勿使用HibernateTemplate和/或HibernateDaoSupport ,应将其视为已弃用。 直接使用SessionFactory 接下来,永远不要在Spring托管的事务中使用openSession ,因为它将在新会话中打开新会话,而不绑定到事务和Spring外部。 SessionFactory上使用getCurrentSession代替。

最后, 绝不捕获并吞下异常,spring的TransactionInterceptor需要异常来决定要做什么(回滚或提交)

重构您的DAO以包括所有这一切。

@Repository
public class TransferDao {

    @Autowired
    private SessionFactory sessionFactory;

    private Session getSession() {
        sessionFactory.getCurrentSession();
    }

    public Account makeTransaction(Transaction transaction, String userName) throws TransactionUnSuccessException {
        Account account = null;
        Session session = getSession();
        updateSelfAccount(transaction, userName, session);
        account = updateAnotherAcccount(transaction, session);
        return account;
    }

从更新的数量来看,另一个观察结果是您有映射问题。 当您的映射正确时,您只需要费心处理User对象的更新/保存,然后其他所有内容都将自动保留。

还有另一点观察,您不应绕过会话,只需调用getSession()方法(已将其添加到dao中)即可。 在整个交易过程中,您应该获得相同的Session

最终观察到,您的dao似乎包含业务逻辑,而应该在服务方法中(例如,检查帐户余额)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM