小伙伴们,在说干货之前,为了更通俗易懂,先来点小菜,岂不是更美滋滋吗~~~嚯嚯
业务讲解:转账案例(小菜)
①小明付钱: update account set money=money-1000 where name=’xiaoming’;
②小红收钱: update account set money=money+1000 where name=’xiaohong’;
流程图:
代码实现:
AccountTest:
public class AccountTest {
private AccountService service = new AccountService();
@Test
public void run1(){
//1、准备数据
String userIn = "xiaohong";//收款人
String userOut = "xiaoming";//付款人
double money = 1000.0;//转账金额
//2、调用service开始转账
boolean flag = service.account(userIn,userOut,money);
//3、根据service的结果,判断转账成功/失败
if(flag){
System.out.println("转账成功");
}else{
System.out.println("转账失败");
}
}
}
AccountService
public class AccountService {
private AccountDao dao = new AccountDao();
/**
* 转账功能
* @param userIn
* @param userOut
* @param money
* @return
*/
public boolean account(String userIn, String userOut, double money) {
try {
//1、付款人 付款
dao.userOut(userOut,money);
//2、收款人 收款
dao.userIn(userIn,money);
} catch (Exception e) {
//出了异常,转账失败
return false;
}
//没出异常,转账成功
return true;
}
}
AccountDao
/**
* 付款人 付款
* @param userOut
* @param money
*/
public void userOut(String userOut, double money) throws SQLException {
//1、获取连接
Connection con = JDBCUtils.getConnection();
//2、获取发送SQL语句对象
PreparedStatement ps = con.prepareStatement("update account set money=money-? where name=?");
ps.setDouble(1,money);
ps.setString(2,userOut);
//3、发送SQL语句
ps.executeUpdate();
//4、关闭资源
JDBCUtils.closeAll(con,ps,null);
}
/**
* 收款人 收款
* @param userIn
* @param money
*/
public void userIn(String userIn, double money) throws SQLException {
//1、获取连接
Connection con = JDBCUtils.getConnection();
//2、获取发送SQL语句对象
PreparedStatement ps = con.prepareStatement("update account set money=money+? where name=?");
ps.setDouble(1,money);
ps.setString(2,userIn);
//3、发送SQL语句
ps.executeUpdate();
//4、关闭资源
JDBCUtils.closeAll(con,ps,null);
}
- 如果付款成功,收款失败,转账失败,会导致付款的钱无法还原而丢失。
解决:
转账失败,所有的操作还原。
转换成功,所有的操作永久保存数据库。
一.数据库事务
1.简述
概念:事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.
- 事务:数据的回收站
- 作用:保证数据完整,保证数据的安全
2.MySQL事务操作
MySQL有两种事务操作,
- 手动事务
- 自动事务(默认开启)
手动事务:
- 手动事务:先手动开启事务,再手动提交 或者手动回滚事务。
sql语句 | 描述 |
start transaction; | 开启事务
开启了一次数据回收站功能。
在当前事务中进行的任何数据的增删改都可以被永久保存/还原。 |
commit; | 提交事务
把当前事务中操作过的数据,永久保存。 关闭当前的手动事务 |
rollback; | 回滚事务
还原事务中操作过的数据。 关闭当前的手动事务 |
例如:
手动事务的注意事项:
1、commit或rollback之后,若需要再次使用事务,必须再次开启事务。
2、事务仅针对DML(增删改)和DQL(查)语句。
若遇到其他语句(例如:DDL语句),事务会强制提交并关闭
- 自动事务:执行任何DML语句时,MySQL自动开启事务,并自动提交事务
注:自动事务无法回滚,只能提交
优点:提升程序员代码测试效率
缺陷:一句一个事务,效率不高,无法自定义事务
自动事务关闭:
临时关闭:
手动开启事务:start transcation;
本次永久关闭:
set autocommit = 0; #0:OFF 1:ON
3.JDBC事务操作
JDBC事务的两大前提:
1、因为转账业务相当于转账事务,所以事务控制代码需要加在service业务层
2、一个事务中的所有的SQL语句,必须使用同一个Connection对象,这样才能保证正常的事务控制
Connection
方法名 | 描述 |
setAutoCommit(boolean flag) | 设置事务是否为自动事务。 参数:true(默认)自动事务 false 手动事务,开启一次手动事务
setAutoCommit(false); 会通知JDBC发送start transaction;给MySQL执行
|
commit(); | 提交事务
会通知JDBC发送commit;给MySQL执行 |
rollback(); | 回滚事务
会通知JDBC发送rollback;给MySQL执行 |
修改代码:
AccountService:
public boolean account(String userIn, String userOut, double money) {
Connection con = null;
try {
//因为事务是在service层,一个事务下的所有操作应该在一个Connection对象中
con = JDBCUtils.getConnection();
//设置手动事务
con.setAutoCommit(false);
//1、付款人 付款
dao.userOut(con, userOut, money);
int a = 1 / 0;
//2、收款人 收款
dao.userIn(con, userIn, money);
//没出异常,提交
con.commit();
} catch (Exception e) {
//出了异常,转账失败
try {
if(con!=null)
con.rollback();
} catch (SQLException e1) {
}
return false;
} finally {
//无论如何都要关闭连接
try {
JDBCUtils.closeAll(con,null,null);
} catch (SQLException e) {
}
}
//没出异常,转账成功
return true;
}
AccountDao:
/**
|
小结:
事务代码加在service层
同一个事务下所有的sql语句,用的是同一个Connection对象
看完恭喜你,又知道了一点点!!!
你知道的越多,不知道的越多!
~感谢志同道合的你阅读, 你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!