事务
事务及处理
事务由一组SQL语句组成。所谓事务处理,是指应用程序保证事务中的SQL语句要么全部都执行,要么一个都不执行。
事务处理是保证数据库中数据完整性与一致性的重要机制。应用程序和数据库建立连接之后,可能使用多条SQL语句操作数据库中的一个表或多个表,例如,一个管理资金转账的应用程序为了完成一个简单的转账业务可能需要两条SQL语句,即需要将数据库user表中id号是0001的记录的userMoney字段的值由原来的100更改为50,然后将id号是0002的记录的userMoney字段的值由原来的20更新为70。应用程序必须保证这两条SQL语句要么全都执行,要么全都不执行。
JDBC事务处理步骤
①用setAutoCommit(booean b)方法关闭自动提交模式
所谓关闭自动提交模式,就是关闭SQL语句的即刻生效性。和数据库建立一个连接对象后,例如con,那么con的提交模式是自动提交模式,即该连接对象con产生的Statement (PreparedStatement对象)对数据库提交任何一条SQL语句操作都会立刻生效,使得数据库中的数据可能发生变化,这显然不能满足事务处理的要求。例如,在转账操作时,将用户0001的userMoney的值由原来的100更改为50的操作不应当立刻生效,而应等到0002用户的userMoney的值由原来的20更新为70后一起生效,如果第二条SQL语句操作未能成功,第一条SQL语句操作就不应当生效。为了能进行事务处理,必须关闭con的这个默认设置。
con对象首先调用setAutoCommit (boolean autoCommit)方法,将参数autoCommit取值false来关闭默认设置:
con.setAutoCommit(false);
注意,先关闭自动提交模式,再获取Statement对象sql:
sql = con.createStatement();
②用commit()方法处理事务
con调用setAutoCommit(false)后,con所产生的Statement对象对数据库提交任何一条SQL语句都不会立刻生效,这样一来,就有机会让Statement对象(PreparedStatement对象)提交多条SQL语句,这些SQL语句就是一个事务。事务中的SQL语句不会立刻生效,直到连接对象con调用commit()方法。con调用commit()方法就是试图让事务中的SQL语句全部生效。
③用rollback()方法处理事务失败
所谓处理事务失败,就是撤销事务所做的操作。con调用commit()方法进行事务处理时,只要事务中任何一个SQL语句未能成功生效,就抛出SQLException异常。在处理SQLException异常时,必须让con调用rollback()方法,其作用是:撤销事务中成功执行的SQL语句对数据库数据所做的更新、插入或删除操作,即撤销引起数据发生变化的SQL语句所产生的操作,将数据库中的数据恢复到commit()方法执行之前的状态。
下面的例子7使用了事务处理,将mess表中number字段是R1001的height的值减少n,并将减少的n增加到字段是R1002的height上(使用了例子2中的GetDBConnection类)。程序代码如下所示:
import java.sql.*;public class Example7 { public static void main(String[] args) { Connection con = null; Statement sql; ResultSet rs; String sqlStr; con = GetDBConnection.connectDB ("students", "root", ""); if(con == null) return; try{ float n = 0.02f; con.setAutoCommit(false); //先关闭自动提交模式 sql = con.createStatement(); //再返回Statement对象 sqlStr = "select name,height from mess where number='R1001'"; rs = sql.executeQuery(sqlStr); rs.next(); float h1 = rs.getFloat(2); System.out.println("事务之前"+rs.getString(1)+"身高:"+h1); sqlStr = "select name,height from mess where number='R1002'"; rs = sql.executeQuery(sqlStr); rs.next(); float h2 = rs.getFloat(2); System.out.println("事务之前"+rs.getString(1)+"身高:"+h2); h1 = h1-n; h2 = h2+n; sqlStr = "update mess set height ="+h1+" where number='R1001'"; sql.executeUpdate(sqlStr); sqlStr = "update mess set height ="+h2+" where number='R1002'"; sql.executeUpdate(sqlStr); con.commit(); //开始事务处理,如果发生异常直接执行catch块 con.setAutoCommit(true); //恢复自动提交模式 String s ="select name,height from mess where number='R1001'or number='R1002'"; rs = sql.executeQuery(s); while(rs.next()) { System.out.println("事务之后"+rs.getString(1)+"身高:"+rs.getFloat(2)); } con.close(); } catch (SQLException e) { try { con.rollback(); //撤销事务所做的操作 } catch(SQLException exp) {} } }}
程序运行结果如图所示:
![b73be415a822aca39a543c400d891927.png](https://i-blog.csdnimg.cn/blog_migrate/70dca3015653e26f07f26500a8d3b0c7.png)
![1efa87ac2c4b911298a4dd7e632b76db.png](https://i-blog.csdnimg.cn/blog_migrate/e3d5e4c849b184c9310a8adfca215d2d.png)
![8e8e9ec89d47746e8f83b7f0b53fe84c.png](https://i-blog.csdnimg.cn/blog_migrate/f618930b3a00970a779b58c04d4f3ef0.jpeg)
![1efa87ac2c4b911298a4dd7e632b76db.png](https://i-blog.csdnimg.cn/blog_migrate/e3d5e4c849b184c9310a8adfca215d2d.png)