分为两个程序开启两个事务,第一个程序开启一个事务进行查询,并且使用行级锁/悲观锁(真nm悲观),锁住相关的记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package TestJDBC.src.TestPessimism; import TestJDBC.src.DBUtil.DBUtil; import java.sql.*; import java.util.Collection; public class TestAffair1 { public static void main(String[] args) { Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { //获取数据库连接对象 conn=DBUtil.getConnection(); //关闭事务自动提交(开启事务) conn.setAutoCommit(false); String sql="select ename,job,sal from EMP where job = ? for update"; ps=conn.prepareStatement(sql); ps.setString(1,"MANAGER"); rs =ps.executeQuery(); while(rs.next()){ String ename=rs.getString("ename"); String job=rs.getString("job"); Double sal=rs.getDouble("sal"); System.out.println(ename+","+job+","+sal); } conn.commit();//在此处添加断点,不让conn提交 } catch (SQLException throwables) { //回滚 if(conn !=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } throwables.printStackTrace(); }finally{ DBUtil.close(conn,ps,rs); } } } |
程序运行至第一个程序断点处停了下来,此时运行第二个程序,第二个程序用于修改被锁定的记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class TestAffair2 { public static void main(String[] args) { Connection conn=null; PreparedStatement ps=null; try { //获取数据库连接对象 conn= DBUtil.getConnection(); //开启事务 conn.setAutoCommit(false); //sql语句,薪资加薪10%,老板福利 String sql="update EMP set sal=sal*1.1 where job=?"; //获取预编译的数据库操作对象 ps=conn.prepareStatement(sql); //给占位符传值进去 ps.setString(1,"MANAGER"); int count = ps.executeUpdate(); System.out.println(count); //提交事务 conn.commit(); } catch (SQLException throwables) { //发生错误,非空回滚 if(conn!=null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } throwables.printStackTrace(); }finally{ DBUtil.close(conn,ps,null); } } } |
由于使用了悲观锁,程序TestAffair2会卡住


将TestAffair中debug中断点恢复

TestAffair2继续运行,运行结果正常