Spring_事务管理(转账案例)

实现一个转账的业务:

OrderDao.java:

package h.l.tx;

import org.springframework.jdbc.core.JdbcTemplate;

public class OrderDao {

	private JdbcTemplate jdbcTemplate;

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	// 模拟转账功能:少钱的方法
	public void desMoney() {
		String sql = "update account set balance=balance-? where username=?";
		jdbcTemplate.update(sql, 1000, "zs");
	}
	// 模拟转账功能:多钱的方法
	public void incMoney() {
		String sql = "update account set balance=balance+? where username=?";
		jdbcTemplate.update(sql, 1000, "ls");
	}
}

OrderService.java:

package h.l.tx;

public class OrderService {

	private OrderDao orderDao;

	public void setOrderDao(OrderDao orderDao) {
		this.orderDao = orderDao;
	}

	// 业务逻辑:转账功能
	public void accountMoney() {
		// 甲少钱
		orderDao.desMoney();
		//手动添加异常
		int i=1/0;
		// 乙多钱
		orderDao.incMoney();
	}
}

Spring配置文件:ApplicationContext.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

	<!-- 配置c3p0连接池 -->
	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 注入属性 -->
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl"
			value="jdbc:mysql://localhost:3306/name?useSSL=true"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>

	<!-- 配置OrderService和OrderDao对象 -->
	<bean id="orderService" class="h.l.tx.OrderService">
		<property name="orderDao" ref="orderDao"></property>
	</bean>
	<bean id="orderDao" class="h.l.tx.OrderDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	
	<!-- 创建JdbcTemplate对象 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
</beans>

测试程序:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

class OrderServiceTest {

	ApplicationContext context;
	@BeforeEach
	void setUp() throws Exception {
		context = new ClassPathXmlApplicationContext(
				"springConfig/ApplicationContext.xml");
	}
	@Test
	void test() {
		OrderService orderService=(OrderService)context.getBean("orderService");
		orderService.accountMoney();
	}

}

执行了上述代码之后,会出现个很严重的问题,就是单元测试没有通过,因为int i=1/0;但是在数据库中zs的钱已经少了1000,,因此解决方法就是加上事务管理:出现异常时,回滚。下面给该功能添加事务功能:

配置文件方式实现:修改上面的ApplicationContext.xml文件即可保证在转账过程中如果出现了异常会进行回滚。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd">
		
	<!-- 配置c3p0连接池 -->
	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 注入属性 -->
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl"
			value="jdbc:mysql://localhost:3306/name?useSSL=true"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入dataSource -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置事务增强 -->
	<tx:advice id="txadvice" transaction-manager="transactionManager">
		<!-- 做事务操作 -->
		<tx:attributes>
			<!-- 设置进行事务操作的方法匹配规则 -->
			<tx:method name="account*"/>
		</tx:attributes>
	</tx:advice>
	<!-- 配置切面 -->
	<aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* h.l.tx.OrderService.*(..))" id="pointcut1"/>
		<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/>
	</aop:config>
	
	<!-- 配置OrderService和OrderDao对象 -->
	<bean id="orderService" class="h.l.tx.OrderService">
		<property name="orderDao" ref="orderDao"></property>
	</bean>
	<bean id="orderDao" class="h.l.tx.OrderDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>

	<!-- 创建JdbcTemplate对象 -->
	<bean id="jdbcTemplate"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
</beans>

注解方式实现:

第一步:修改ApplicationContext.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd">
		
	<!-- 配置c3p0连接池 -->
	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 注入属性 -->
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl"
			value="jdbc:mysql://localhost:3306/name?useSSL=true"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 注入dataSource -->
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 开启事务注解 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
	
	<!-- 配置OrderService和OrderDao对象 -->
	<bean id="orderService" class="h.l.tx.OrderService">
		<property name="orderDao" ref="orderDao"></property>
	</bean>
	<bean id="orderDao" class="h.l.tx.OrderDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>

	<!-- 创建JdbcTemplate对象 -->
	<bean id="jdbcTemplate"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
</beans>

第二步在需要添加事务功能的类上加上@Transactional注解:如下即可:

package h.l.tx;

import org.springframework.transaction.annotation.Transactional;

@Transactional
public class OrderService {

	private OrderDao orderDao;

	public void setOrderDao(OrderDao orderDao) {
		this.orderDao = orderDao;
	}

	// 业务逻辑:转账功能
	public void accountMoney() {
		// 甲少钱
		orderDao.desMoney();
		//出现异常
		int i=1/0;
		// 乙多钱
		orderDao.incMoney();
	}
}

注:以上文章仅是个人学习过程总结,若有不当之处,望不吝赐教

扫描二维码关注公众号,回复: 4309592 查看本文章

猜你喜欢

转载自blog.csdn.net/m0_37265215/article/details/84646626