更多Spring开发在框架开发
事务是什么不再多说。Spring事务管理主要用声明式事务管理,通过调用PlatformTransactionManager
接口的方式实现,而Spring的事务管理的接口针对dao层框架提供了不同的实现类:(本文主要对传统SpringJDBC方法进行讲解,即下图中的第一个)
案例目标: 先向数据库中添加两个用户,然后一个用户向另一个用户进行转帐,将转帐的方法进行事务管理。
项目环境:导入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)
);
User类
package edu.kmust.user.entity;
import java.math.BigDecimal;
public class User {
private Integer userId ;
private String userName;
private BigDecimal userSal;
//省略set与get方法
}
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);
}
}
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 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);
}
}
applicationContext.xml ,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>
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 userList = new ArrayList();
userList.add(user1);
userList.add(user2);
//添加两个用户
/*userService.addUser(user1);
userService.addUser(user2);*/
/*
* 黄思给我赵玉强转200元
*/
BigDecimal money = new BigDecimal("200") ;
userService.accountMoney(userList, money);
}
}
上述转账案例不牵扯事务的管理,如果调用减少钱的方法后,因为实际环境出现异常,而不执行后续增加钱的方法,这是不可以的,所以,需要事务管理对转帐业务进行回滚操作。
在spring配置文件中加入事务管理如下,对service中的accountMoney方法进行事务管理,service中不需要进行其他修改
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="accountMoney*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* edu.kmust.user.service.UserService.accountMoney(..))" id="point_accountMoney"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="point_accountMoney"/>
aop:config>
使用注解方式比XML配置文件方式要简单多
在spring配置文件中加入事务管理如下
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<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 {
.....
}
https://download.csdn.net/download/g425680992/10659176