Spring事务:声明式事务管理案例-转账(XML、注解)

代码魔法师 2024-02-21 ⋅ 26 阅读

1. 简介

在Spring框架中,事务管理是一个非常重要的功能,它可以帮助我们简化数据库操作过程中的事务管理代码。Spring提供了两种方式来实现声明式事务管理:XML配置和注解配置。

本文将以一个转账的案例来介绍如何使用Spring进行声明式事务管理,并提供了两种实现方式:基于XML配置的方式和基于注解配置的方式。

2. 转账案例需求

我们的转账案例有以下几个需求:

  • 用户A向用户B转账一定金额
  • 要求在转账过程中,要么全部执行成功,要么全部回滚,保证数据的一致性

3. 基于XML配置的声明式事务管理

3.1 配置数据源

首先,我们需要在Spring配置文件中配置数据源,以便让Spring知道要管理哪个数据库的事务。例如,在applicationContext.xml中添加以下配置:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>
</bean>

3.2 配置事务管理器

接下来,我们需要配置事务管理器,用于对数据库事务进行管理。例如,在applicationContext.xml中添加以下配置:

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

3.3 配置事务通知

然后,我们需要在Spring配置文件中配置事务通知,用于指定哪些方法需要进行事务管理。在本例中,我们需要对转账方法进行事务管理。例如,在applicationContext.xml中添加以下配置:

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="transfer" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

3.4 配置切点和切面

最后,我们需要配置切点和切面,将事务通知应用到对应的切点上。例如,在applicationContext.xml中添加以下配置:

<aop:config>
    <aop:pointcut id="transferPointcut" expression="execution(* com.example.service.TransferService.transfer(..))"/>
    <aop:advisor advice-ref="transactionAdvice" pointcut-ref="transferPointcut"/>
</aop:config>

现在,我们已经完成了基于XML配置的声明式事务管理的配置。接下来,我们可以实现具体的业务逻辑。

3.5 实现业务逻辑

我们可以创建一个TransferService接口和对应的实现类TransferServiceImpl来实现转账的具体逻辑。例如:

public interface TransferService {
    void transfer(int fromAccount, int toAccount, double amount);
}
@Service
public class TransferServiceImpl implements TransferService {
    @Autowired
    private AccountDao accountDao;

    @Transactional
    public void transfer(int fromAccount, int toAccount, double amount) {
        double fromBalance = accountDao.getBalance(fromAccount);
        double toBalance = accountDao.getBalance(toAccount);

        if (fromBalance >= amount) {
            accountDao.updateBalance(fromAccount, fromBalance - amount);
            accountDao.updateBalance(toAccount, toBalance + amount);
        } else {
            throw new InsufficientBalanceException("Insufficient balance");
        }
    }
}

TransferServiceImpl中,我们使用了@Transactional注解来标记需要进行事务管理的方法。

3.6 测试

现在,我们可以进行测试了。例如:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TransferServiceTest {
    @Autowired
    private TransferService transferService;

    @Test
    public void testTransfer() {
        transferService.transfer(1001, 1002, 100);
    }
}

在上述测试中,我们注入了TransferService实例,并调用了转账方法。

4. 基于注解配置的声明式事务管理

除了使用XML配置外,我们还可以使用注解来配置声明式事务管理。

4.1 配置事务管理器

首先,我们需要在applicationContext.xml中配置事务管理器,如下所示:

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

4.2 开启注解配置

然后,我们需要在applicationContext.xml中启用Spring事务注解配置,如下所示:

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

4.3 实现业务逻辑

接下来,我们只需要在TransferServiceImpl类的转账方法上添加@Transactional注解即可,如下所示:

@Service
public class TransferServiceImpl implements TransferService {
    @Autowired
    private AccountDao accountDao;

    @Transactional
    public void transfer(int fromAccount, int toAccount, double amount) {
        double fromBalance = accountDao.getBalance(fromAccount);
        double toBalance = accountDao.getBalance(toAccount);

        if (fromBalance >= amount) {
            accountDao.updateBalance(fromAccount, fromBalance - amount);
            accountDao.updateBalance(toAccount, toBalance + amount);
        } else {
            throw new InsufficientBalanceException("Insufficient balance");
        }
    }
}

4.4 测试

最后,我们可以进行基于注解配置的声明式事务管理的测试,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TransferServiceTest {
    @Autowired
    private TransferService transferService;

    @Test
    public void testTransfer() {
        transferService.transfer(1001, 1002, 100);
    }
}

5. 总结

本文介绍了基于XML配置和注解配置两种方式实现Spring声明式事务管理的案例。通过使用声明式事务管理,我们可以简化数据库操作中的事务管理代码,并保证数据的一致性和完整性。根据实际情况选择适合的方式来配置Spring的事务管理,可以提升开发效率和代码的可维护性。


全部评论: 0

    我有话说: