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(); //手动回滚一定要提交 } } }
时间: 2024-10-16 00:23:04