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);