事务的概念
事务处理在数据库开发中有着非常重要的作用,所谓事务就是所有的操作要么一起成功,要么一起失败,事务
本身具有原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durability)4 个特
性,这 4 个特性也被称为 ACID 特征。
- 原子性:原子性是事务最小的单元,是不可再分隔的单元,相当于一个个小的数据库操作,这些操作必须同时成功,如果一个失败了,则一切的操作将全部失败。
- 一致性:指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一致状态。
- 隔离性:多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作时,才可以看到结果;
- 持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
MySQL 对事务的支持
命令 | 描述 |
---|---|
SET AUTOCOMMIT=0 | 取消自动提交处理,开启事务处理 |
SET AUTOCOMMIT=1 | 打开自动提交处理,关闭事务处理 |
START TRANSACTION | 启动事务 |
BEGIN | 启动事务,相当于执行 START TRANSACTION |
COMMIT | 提交事务 |
ROLLBACK | 回滚全部事务 |
SAVEPOINT 事务保存点名称 | 设置事务保存点 |
ROLL BACK TO SAVEPOINT 保存点名称 | 回滚操作到保存点 |
JDBC 事务处理
张三向李四转500
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.cn.zj.JDBCUtil.DbUtil;
public class demo {
private static DbUtil dbUtil=new DbUtil();
/**
* 转出
* @param con
* @param accountName
* @param account
* @throws Exception
*/
private static void outCount(Connection con,String accountName,int account)throws Exception{
String sql="update t_account set accountBalance=accountBalance-? where accountName=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, account);
pstmt.setString(2, accountName);
pstmt.executeUpdate();
}
/**
* 转如
* @param con
* @param accountName
* @param account
* @throws Exception
*/
private static void inCount(Connection con,String accountName,int account)throws Exception{
String sql="update t_account set accountBalance=accountBalance+? where accountName=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, account);
pstmt.setString(2, accountName);
pstmt.executeUpdate();
}
public static void main(String[] args) {
Connection con=null;
try{
con=dbUtil.getCon();
System.out.println("张三开始向李四转账!");
int account=500;
outCount(con,"张三",account);
inCount(con,"李四",account);
System.out.println("转账成功");
}catch(Exception e){
e.printStackTrace();
}finally{
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
若转账错误,张三转了500,但李四没有收到五百,就要用事务,事务的原子性,一致性
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.cn.zj.JDBCUtil.DbUtil;
public class demo {
private static DbUtil dbUtil=new DbUtil();
/**
* 转出
* @param con
* @param accountName
* @param account
* @throws Exception
*/
private static void outCount(Connection con,String accountName,int account)throws Exception{
String sql="update t_account set accountBalance=accountBalance-? where accountName=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, account);
pstmt.setString(2, accountName);
pstmt.executeUpdate();
}
/**
* 转入
* @param con
* @param accountName
* @param account
* @throws Exception
*/
private static void inCount(Connection con,String accountName,int account)throws Exception{
//转入sql语句错误
String sql="update t_account set accountBalance=account+? where accountName=?";
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setInt(1, account);
pstmt.setString(2, accountName);
pstmt.executeUpdate();
}
public static void main(String[] args) {
Connection con=null;
try{
con=dbUtil.getCon();
/**
* 事务处理
*/
con.setAutoCommit(false); //取消自动提交
System.out.println("张三开始向李四转账!");
int account=500;
outCount(con,"张三",account);
inCount(con,"李四",account);
System.out.println("转账成功");
}catch(Exception e){
e.printStackTrace();
try {
con.rollback(); //回滚
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}finally{
try {
con.commit(); //提交事务
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
========================================================================================
DbUtil.java工具类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* 通用方法
* @author Administrator
*
*/
public class DbUtil {
//驱动名称
private static String jdbcName="com.mysql.jdbc.Driver";
//mysql数据库地址
private static String dbUrl="jdbc:mysql://localhost:3306/db_band?useUnicode=true&characterEncoding=UTF-8";
//用户名
private static String dbUserName="root";
//密码
private static String dbPassword="root";
//获取数据库连接的方法
public Connection getCon() throws Exception{
Class.forName(jdbcName); //加载驱动
Connection con=DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
return con;
}
//关闭数据库连接
public void close(Statement stmt,Connection con)throws Exception{
if(stmt!=null){
stmt.close();
if(con!=null){
con.close();
}
}
}
}