数据库事务:
JDBC程序中当一个连接对象被创建时,默认情况下是自动提交事务,每次执行一个sql语句时,如果执行成功就会向数据库自动提交,而不能回滚。
JDBC程序中为了让多个sql语句作为一个事务执行。
个人理解的事务,做一件事情,有ABCDE…多个步骤,如果后面的步骤中有无法执行的,那么即使前面做过的ABCD几件事情也要撤销,给恢复成原来没有做过的样子,一件事情要么做就做完,要么就不做,万万不能做一半扔下个烂摊子。
普通买书的过程
这本JavaWeb书,单价50元,张飞同学有80元
先买一本,书的库存减少,张飞的账户余额减少。
张飞剩余30元,这时候他的月不够,但是他尝试买第二本书,这个时候就会出现问题:图书的库存较少了,但是张飞的余额却没有减少,还是30元。
以下是没有添加事务的程序:
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 TransactionTesr {
@Test public void test() throws Exception { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///test"; Connection conn = DriverManager.getConnection(url , "root", "abc123"); String sql = "update book set stock = stock - 1 where isbn = ?"; String sql2 = "update account set balance = balance - ? where id = ?"; PreparedStatement pst = conn.prepareStatement(sql); pst.setString(1, "10023"); pst.executeUpdate(); pst = conn.prepareStatement(sql2); pst.setDouble(1, 50.00); pst.setInt(2, 1); pst.executeUpdate(); conn.close(); pst.close(); }
|
以下是添加事务的程序:
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
| @Test public void testTransaction() throws Exception { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///test"; Connection conn = DriverManager.getConnection(url , "root", "abc123"); conn.setAutoCommit(false); PreparedStatement pst = null; String sql = "update book set stock = stock - 1 where isbn = ?"; String sql2 = "update account set balance = balance - ? where id = ?"; try { pst = conn.prepareStatement(sql); pst.setString(1, "10023"); pst.executeUpdate(); pst = conn.prepareStatement(sql2); pst.setDouble(1, 50.00); pst.setInt(2, 1); pst.executeUpdate(); conn.commit(); } catch (Exception e) { conn.rollback(); e.printStackTrace(); } conn.close(); pst.close(); }
}
|
添加事务之后,张飞同学的余额不足时候,买书会失败,书的库存不会减少,张飞的月也不会变化。