目标
1,使用jdbc代码,添加数据库事务动作!
2,开启事务
3,事务提交 / 事务回滚
事务概念回顾
// 事务概念
数据库事务就是一种SQL语句执行的缓存机制,不会单条执行完毕就更新数据库数据,最终根据缓
存内的多条语句执行结果统一判定!
一个事务内所有语句都成功及事务成功,我们可以触发commit提交事务来结束事务,更新数据!
一个事务内任意一条语句失败,及事务失败,我们可以触发rollback回滚结束事务,
数据回到事务之前状态!
举个例子:
临近高考,你好吃懒做,偶尔还瞎花钱,父母也只会说'你等着!',待到高考完毕!
成绩600+,翻篇,庆祝!
成绩200+,翻旧账,男女混合双打!
//优势
允许我们在失败情况下,数据回归到业务之前的状态!
//场景
一个业务涉及多条修改数据库语句!
例如: 经典的转账案例,转账业务(加钱和减钱)
批量删除(涉及多个删除)
批量添加(涉及多个插入)
// 事务特性
1. 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2. 一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
3. 隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4. 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
// 事务类型
自动提交 : 每条语句自动存储一个事务中,执行成功自动提交,执行失败自动回滚! (MySQL)
手动提交: 手动开启事务,添加语句,手动提交或者手动回滚即可!
// sql开启事务方式
针对自动提交: 关闭自动提交即可,多条语句添加以后,最终手动提交或者回滚! (推荐)
SET autocommit = off; //关闭当前连接自动事务提交方式
# 只有当前连接有效
# 编写SQL语句即可
SQL
SQL
SQL
#手动提交或者回滚 【结束当前的事务】
COMMIT / ROLLBACK ;
手动开启事务: 开启事务代码,添加SQL语句,事务提交或者事务回滚! (不推荐)
// 呼应jdbc技术
try{
connection.setAutoCommit(false); //关闭自动提交了
//注意,只要当前connection对象,进行数据库操作,都不会自动提交事务
//数据库动作!
//statement - 单一的数据库动作 c u r d
connection.commit();
}catch(Execption e){
connection.rollback();
}
数据库表数据
-- 继续在huan的库中创建银行表
CREATE TABLE t_bank(
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '账号主键',
account VARCHAR(20) NOT NULL UNIQUE COMMENT '账号',
money INT UNSIGNED COMMENT '金额,不能为负值') ;
INSERT INTO t_bank(account,money) VALUES
('ergouzi',1000),('lvdandan',1000);
代码结构设计
JDBC事务实现
BankDao层类
package com.jdbc.transaction;
import java.sql.*;
/**
* @author : Aurora
* @Date : 2023/1/4
* @Describe : bank表的数据库操作方法存储类
*/
public class BankDao {
/**
* 加钱的数据库操作方法(JDBC)
*
* @param account 加钱的行号
* @param money 加钱的金额
*/
public void add(String account, int money,Connection conn) throws ClassNotFoundException, SQLException {
//编写SQL语句结果
String sql = "update t_bank set money = money + ? where account = ?;";
//创建statement
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//占位符
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送sql语句
preparedStatement.executeUpdate();
//关闭资源
preparedStatement.close();
System.out.println("加钱成功!");
}
/**
* 减钱的数据库操作方法(JDBC)
*
* @param account 减钱的行号
* @param money 减钱的金额
*/
public void sub(String account, int money,Connection conn) throws SQLException, ClassNotFoundException {
//编写SQL语句结果
String sql = "update t_bank set money = money - ? where account = ?;";
//创建statement
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//占位符
preparedStatement.setObject(1, money);
preparedStatement.setString(2, account);
//发送sql语句
preparedStatement.executeUpdate();
//关闭资源
preparedStatement.close();
System.out.println("减钱成功!");
}
}
BankService类
package com.jdbc.transaction;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @author : Aurora
* @Date : 2023/1/4
* @Describe : 银行卡业务方法,调用dao方法
*/
public class BankService {
/**
* TODO: 事务添加在业务方法中!
* 利用try catch代码块,开启事务和提交事务,以及事务回滚!
* 将connection传入dao层即可,dao只负责使用,不要close();
*
* @param addAccount
* @param subAccount
* @param money
* @throws SQLException
* @throws ClassNotFoundException
*/
public void transfer(String addAccount, String subAccount, int money) throws SQLException, ClassNotFoundException {
BankDao bankDao = new BankDao();
//一个事务的最基本要求,必须是同一个连接对象 connection
//[一个转账方法,属于同一个事务 (加钱,减钱)]
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:13306/huan", "root", "123456");
try {
//开启事务
//关闭事务提交
conn.setAutoCommit(false);
//执行数据库动作
bankDao.add(addAccount, money, conn);
System.out.println("--------------------");
bankDao.sub(subAccount, money, conn);
//事务提交
conn.commit();
} catch (Exception e) {
//事务回滚
conn.rollback();
//抛出异常
throw e;
} finally {
conn.close();
}
}
@Test
public void start() throws SQLException, ClassNotFoundException {
//二狗子给驴蛋蛋转500
transfer("lvdandan", "ergouzi", 500);
}
}
测试类
package com.jdbc.transaction;
import java.sql.SQLException;
/**
* @author : Aurora
* @Date : 2023/1/4
* @Describe : 启动类
*/
public class Test {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//二狗子给驴蛋蛋转500
BankService bankService = new BankService();
bankService.transfer("lvdandan", "ergouzi", 500);
}
}
按着案例敲,深入思考