版权声明:本文为博主原创文章,未经博主允许不得转载。Q425680992 https://blog.csdn.net/g425680992/article/details/82624441
更多Spring开发在框架开发
1 Spring事务管理?
事务是什么不再多说。Spring事务管理主要用声明式事务管理,通过调用PlatformTransactionManager
接口的方式实现,而Spring的事务管理的接口针对dao层框架提供了不同的实现类:(本文主要对传统SpringJDBC方法进行讲解,即下图中的第一个)
声明事务的方式有如下两种:
- 基于XML配置文件实现
- 基于注解实现
2 Spring 事务管理案例
案例目标: 先向数据库中添加两个用户,然后一个用户向另一个用户进行转帐,将转帐的方法进行事务管理。
项目环境:导入jar包,导入spring相关包(ioc基本包,jdbcTemplate包,aop包),mysql相关包,日志相关包,c3p0相关包。
项目数据库创建:
create database db_springTransaction ;
create table tb_user(
userId int(20) primary key,
userName varchar(50) default null,
userSal decimal(7,2)
);
2.1 实体类
User类
package edu.kmust.user.entity;
import java.math.BigDecimal;
public class User {
private Integer userId ;
private String userName;
private BigDecimal userSal;
//省略set与get方法
}
2.2 dao
UserDao类
package edu.kmust.user.dao;
import java.math.BigDecimal;
import org.springframework.jdbc.core.JdbcTemplate;
import edu.kmust.user.entity.User;
/**
* 持久层User
* @author zhaoyuqiang
*
*/
public class UserDao {
private JdbcTemplate jdbcTemplate ;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 用户少钱,去money的负数
* @param user
*/
public void lessMoney(User user,BigDecimal money) {
String sql = "update tb_user set userSal=userSal+? where userName=?" ;
int rows = jdbcTemplate.update(sql,
money.multiply(new BigDecimal(-1)),user.getUserName());
System.out.println("少钱成功,影响记录的行数="+rows);
}
/**
* 用户多钱
* @param user
*/
public void moreMoney(User user,BigDecimal money) {
String sql = "update tb_user set userSal=userSal+? where userName=?" ;
int rows = jdbcTemplate.update(sql, money,user.getUserName());
System.out.println("多钱成功,影响记录的行数="+rows);
}
/**
* 添加用户
* @param user
*/
public void add(User user) {
String sql = "insert into tb_user values(?,?,?)" ;
int rows = jdbcTemplate.update(sql, user.getUserId(),user.getUserName(),user.getUserSal());
System.out.println("添加用户成功,影响记录的行数="+rows);
}
}
2.3 service
UserService类
package edu.kmust.user.service;
import java.math.BigDecimal;
import java.util.List;
import edu.kmust.user.dao.UserDao;
import edu.kmust.user.entity.User;
/**
* 业务层User
* @author zhaoyuqiang
*
*/
public class UserService {
private UserDao userDao ;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 转帐业务:
* 一个用户给另一个用户转状,一个用户钱增多,一个用户钱减少
* @param userList
*/
public void accountMoney(List<User> userList,BigDecimal money) {
userDao.lessMoney(userList.get(0),money);
userDao.moreMoney(userList.get(1),money);
}
/**
* 添加用户
* @param user
*/
public void addUser(User user) {
userDao.add(user);
}
}
2.4 Spring配置文件
applicationContext.xml ,Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入一个全面的Spring约束 -->
<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">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 注入属性 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///db_springTransaction"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="userService" class="edu.kmust.user.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="edu.kmust.user.dao.UserDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
2.5 test
package edu.kmust.user.test;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import edu.kmust.user.entity.User;
import edu.kmust.user.service.UserService;
/**
* 测试类,测试添加功能与没有事务的转帐
* @author zhaoyuqiang
*
*/
public class UserTest {
@Test
public void test01() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
//创建两个用户
User user1 = new User();
user1.setUserId(1);
user1.setUserName("黄思");
user1.setUserSal(new BigDecimal("1000.520"));
User user2 = new User();
user2.setUserId(2);
user2.setUserName("赵玉强");
user2.setUserSal(new BigDecimal("1000.520"));
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
//添加两个用户
/*userService.addUser(user1);
userService.addUser(user2);*/
/*
* 黄思给我赵玉强转200元
*/
BigDecimal money = new BigDecimal("200") ;
userService.accountMoney(userList, money);
}
}
3 service中的事务管理
上述转账案例不牵扯事务的管理,如果调用减少钱的方法后,因为实际环境出现异常,而不执行后续增加钱的方法,这是不可以的,所以,需要事务管理对转帐业务进行回滚操作。
3.1 XMl配置文件的方式进行事务管理
在spring配置文件中加入事务管理如下,对service中的accountMoney方法进行事务管理,service中不需要进行其他修改
<!-- 事务:第一步,配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入属性dataSource,表明事务管理器要对哪个数据源进行管理 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务:第二步,配置事务增强
transaction-manager的值与事务管理器的id值一样
-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!-- 做事务操作 -->
<tx:attributes>
<!-- 设置进行事务操作的方法配置规则,即在哪儿方法里面进行事务操作
name:是进行事务操作的方法
propagation:是隔离级别,可以不写,这里采用mysql的默认级别
-->
<tx:method name="accountMoney*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 事务:第三步,配置aop切面 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* edu.kmust.user.service.UserService.accountMoney(..))" id="point_accountMoney"/>
<!-- 切面 ,把哪个增强用在哪个切入点上
advice-ref: 事务增强的id
pointcut-ref : 切入点id
-->
<aop:advisor advice-ref="txadvice" pointcut-ref="point_accountMoney"/>
</aop:config>
3.2 注解的方式进行事务管理
使用注解方式比XML配置文件方式要简单多
在spring配置文件中加入事务管理如下
<!-- 事务:第一步,配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入属性dataSource,表明事务管理器要对哪个数据源进行管理 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务注解方式: 第二步,开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager" />
在要使用事务的方法accountMoney所在类UserService上面添加注解
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserService {
.....
}