package mysql;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import org.junit.Test;
//事物特性ACID
//原子性,指事务中的操作要么都发生,要么都不发生
//一致性。指事务前后数据的完整性必须保持一致(甲乙2人总额2000元,甲转账乙100元后,转账后总额还是2000元)
//隔离性。多个事务并发访问数据库的时候,一个事务间的操作不能干扰其他事务,要相互隔离
//持久性:指事务一旦提交(commit),对数据库的改变是持久的,即使数据库故障也不应对数据有影响
//数据库的隔离级别Seraializable(串行化,最高级别,能处理各种问题,但数据库效率低下),repeated read,read commit,read uncommit
/*
create table account
(
id int primary key auto_increment,
name varchar(20),
price int
);
/*
* 事务,要么执行,要不执行
* start transaction
update account set price=price-100 where name='a';
update account set price=price+100 where name='b';
* sql2语句
* commit(一定要执行commit才生效,不然回滚)
*/
public class 事务 {
@Test
public void test1() throws SQLException
{
Statement s=null;
Connection con=DBHelper.getConnection();
try{
con.setAutoCommit(false);//不能一条一条执行sql
String sql1="update account set price=price-100 where name='a'";
String sql2="update account set price=price+100 where name='b'";
s=con.createStatement();
s.executeUpdate(sql1);
int i=8/0; //这边有错,程序自动回滚
s=con.createStatement();
s.executeUpdate(sql2);
con.commit();
System.out.println("success....");
}
catch (Exception e) {
con.rollback();//自动回滚
}
}
@Test
public void test2() throws SQLException //手动回滚事务,假如第二条sql执行错误,程序回滚,让第一条sql正常插入数据库
{
Statement s=null;
Connection con=DBHelper.getConnection();
Savepoint p=null;
try{
con.setAutoCommit(false);//不能一条一条执行sql
String sql1="update account set price=price-100 where name='a'";
String sql2="update account set price=price+100 where name='b'";
String sql3="update account set price=price+100 where name='c'";
s=con.createStatement();
s.executeUpdate(sql1);
p=con.setSavepoint(); //保存点
int i=12/0; //这边出错了,上一条依然插入数据库
s=con.createStatement();
s.executeUpdate(sql2);
s=con.createStatement();
s.executeUpdate(sql3);
con.commit();
System.out.println("success....");
}
catch (Exception e) {
con.rollback(p); //回滚到第一个,第一个要执行
con.commit(); //手动回滚一定要提交
}
}
}