事务
1.什么是事务:
当某一功能或逻辑涉及到多个sql语句(DML),此时,我们要
保证,要么都执行,要么都不执行。这种情况就是一个事务。
2.事务的特点:
原子性:这个事务要做就做完,要么不做。
一致性:做之前,保证数据一致;做之后,也要保证数据的一致。
隔离性:事务并发时,要对事务进行隔离。
持久性:最好数据要持久保存到数据中。
3. 提交
JDBC对事务的支持,默认都是执行完sql语句自动提交到数据库,不会回滚,
如果一个事务涉及到多个sql时,取消自动(自动提交),最好设置成手动提交,中间出现异常时,我们可以回滚。
事务完成后,要保持数据的持久性,需要手动提交。
例如: conn.setAutoCommit(true);默认的话为自动提交,
每执行一个update ,delete或者insert的时候都会自动提交到数据库,无法回滚事务。
设置conn.setautocommit(false); 只有程序调用
conn.commit()的时候才会将先前执行的语句一起提交到数据库,这样就实现了数据库的事务。
保持了数据的持久性。
4.经典案例:银行转账
1. 2 public class DBUtil2 { 3 private static String driver; 4 private static String url; 5 private static String user; 6 private static String pwd; 7 /**读取配置文件,只需要加载一次*/ 8 static { 9 try {//从db文件读取出来内容 10 /*文件字符流:默认当前文件路径在工程名下。 11 * :通过当前类的类加载器所获取的流读取配置文件 12 */ 13 FileReader fr=new FileReader("db.properties"); 14 Properties prop=new Properties(); 15 prop.load(fr); 16 driver=prop.getProperty("driver"); 17 url=prop.getProperty("url"); 18 user=prop.getProperty("user"); 19 pwd=prop.getProperty("pwd"); 20 Class.forName(driver);//1加载驱动 21 } catch (Exception e) { 22 e.printStackTrace(); 23 /*db.properties文件内容: 24 driver=oracle.jdbc.driver.OracleDriver 25 #driver=oracle.jdbc.OracleDriver 26 url=jdbc:oracle:thin:@localhost:1521:orcl 27 user=scott 28 pwd=1234 29 */ 30 } 31 } 32 33 public static Connection getconn() {//2.建立连接 34 Connection conn=null; 35 try { 36 conn = DriverManager.getConnection( 37 url, user, pwd); 38 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } 42 return conn; 43 } 44 public static void colseconn(Connection conn) { 45 try { 46 if(conn!=null) { 47 conn.close(); 48 } 49 } catch (Exception e) { 50 e.printStackTrace(); 51 } 52 } 53 public static void main(String[] args) { 54 System.out.println(getconn());//返回连接对象 55 } 56 } 57 2. 58 public class BankTest { 59 //账户转账 60 public static void main(String[] args) { 61 String account="za1001"; 62 String toAccount="ls1002"; 63 double money=100; 64 Map<String,String> map = 65 moneyToMoney(account,toAccount,money); 66 if(map.containsKey("ok")){ 67 System.out.println(map.get("ok")); 68 }else{ 69 System.out.println(map.get("fail")); 70 } 71 } 72 73 74 public static Map<String,String> moneyToMoney(String account, 75 String toAccount,double money){ 76 Connection conn=null; 77 Map<String,String> map=null; 78 try { 79 conn=DBUtil2.getconn(); 80 map = new HashMap<String,String>(); 81 //取消自动提交 82 conn.setAutoCommit(false); 83 84 String sql="select * from bank_money where account=?"; 85 PreparedStatement ps=conn.prepareStatement(sql); 86 ps.setString(1, account); 87 ResultSet rs=ps.executeQuery(); 88 if(!rs.next()) { 89 map.put("fail", "转出账户不存在"); 90 return map; 91 } 92 double mo1=rs.getDouble("money");//转出账户的余额; 93 //转入账户是否存在,又给?设值 94 ps.setString(1, toAccount); 95 rs=ps.executeQuery(); 96 if(!rs.next()) { 97 map.put("fail", "转入账户不存在"); 98 return map; 99 } 100 double mo2=rs.getDouble("money"); 101 if(money>mo1) { 102 map.put("fail", "余额不足,不能转出"); 103 return map; 104 } 105 sql="update bank_money set money=? where account=?"; 106 ps=conn.prepareStatement(sql); 107 //转出账户 108 ps.setDouble(1, mo1-money);//转出账户转账 109 ps.setString(2, account); 110 int c1=ps.executeUpdate(); 111 112 //转入账户修改money 113 ps.setDouble(1, mo2+money); 114 ps.setString(2, toAccount); 115 int c2=ps.executeUpdate(); 116 117 if(c1!=1||c2!=1) { 118 map.put("fail", "交易失败"); 119 } 120 map.put("ok", "交易成功"); 121 122 conn.commit(); 123 } catch (Exception e) { 124 e.printStackTrace(); 125 //回滚 126 try { 127 conn.rollback(); 128 } catch (SQLException e1) { 129 e1.printStackTrace(); 130 } 131 }finally { 132 DBUtil2.colseconn(conn); 133 } 134 return map; 135 } 136 137 } 138
3.数据库语句 create table bank_money( id number primary key, account varchar2(50) not null, pwd varchar2(50) not null, money number(10,2) ); insert into bank_money values(1,'za1001','123456',10000); insert into bank_money values(2,'ls1002','654321',5000);