(一)什么是事物?java
事务是逻辑上的一组操做,组成这组操做的各个单元,要不全都成功要不全都失败,这个特性就是事务。事务是必须知足4个条件(ACID): Atomicity(原子性)、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性)。mysql
(二)事物提交与回滚sql
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会立刻执行 COMMIT 操做。所以要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。数据库
例子:默认JDBC设置spa
public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = DBUtil.getConn(); //conn.setAutoCommit(false);//设置自动事务提交为false //a给b转帐-----a帐户减去100块钱;b帐户增长100块钱 ps = conn.prepareStatement("update account set salary=salary-100 where name=?"); ps.setString(1, "a"); ps.executeUpdate(); int i = 1 / 0; //设置异常 ps = conn.prepareStatement("update account set salary=salary+100 where name=?"); ps.setString(1, "b"); ps.executeUpdate(); conn.commit(); } catch (Exception e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { DBUtil.close(conn, ps, rs); } }
代码解析:默认状况下每执行一条sql语句,就是执行一次事务,也就是每一条sql语句的执行都会是一次事务的提交。在这个例子中若是a给b转帐,a帐户减去100的sql语句执行成功,这时伴随着一次的事务提交,数据库中的a帐户金额减去100;而再执行b的帐务增长100sql语句以前,出现了异常,这里我设了一个除以零异常,此时程序终止,bsql语句再也不执行。a帐户扣了100,而b帐户则金额不变。这时数据出错。命令行
解决方法是:经过conn.setAutoCommit(false);方法设置事务自动提交为false。这时每一次的sql语句执行完成后就不会提交事务,数据库中的数据并不会发生改变,当俩个sql都执行完成,而后调用coon.commit();方法提交事务,此时数据库中的数据才会真正的改变。若是中途发生异常,经过conn.rollback();方法回滚,此时以前执行的sql语句的结果并不会提交。这样数据就不会出错了。code
知识点:当一个链接对象被建立时,默认状况下JDBC是自动提交事务:每次执行一个 SQL 语句时,若是执行成功,就会向数据库自动提交,而不能回滚。如想多条SQL在同一事务中,可以使用下列语句:
☆JDBC控制事务语句
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();对象
例子:设置setAutoCommit(false),和事物回滚点事务
public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; Savepoint point = null; try { conn = DBUtil.getConn(); conn.setAutoCommit(false);//设置自动事务提交为false //a给b转帐-----a帐户减去100块钱;b帐户增长100块钱 ps = conn.prepareStatement("update account set salary=salary-100 where name=?"); ps.setString(1, "a"); ps.executeUpdate(); ps = conn.prepareStatement("update account set salary=salary+100 where name=?"); ps.setString(1, "b"); ps.executeUpdate(); point = conn.setSavepoint(); int i = 1 / 0; //a给b转帐-----a帐户减去100块钱;b帐户增长100块钱 ps = conn.prepareStatement("update account set salary=salary-100 where name=?"); ps.setString(1, "a"); ps.executeUpdate(); ps = conn.prepareStatement("update account set salary=salary+100 where name=?"); ps.setString(1, "b"); ps.executeUpdate(); conn.commit(); } catch (Exception e) { e.printStackTrace(); try { if(point == null) { conn.rollback(); } else { conn.rollback(point); conn.commit(); } } catch (SQLException e1) { e1.printStackTrace(); } } finally { DBUtil.close(conn, ps, rs); } }
知识点:ci
☆设置事务回滚点
Savepoint sp = conn.setSavepoint();
Conn.rollback(sp); //回滚
Conn.commit(); //回滚后必需要提交
(三)在MYSQL 事务处理主要有两种方法:
一、用 BEGIN, ROLLBACK, COMMIT来实现
二、直接用 SET 来改变 MySQL 的自动提交模式:
例子:
mysql> use RUNOOB; Database changed mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb; # 建立数据表 Query OK, 0 rows affected (0.04 sec) mysql> select * from runoob_transaction_test; Empty set (0.01 sec) mysql> begin; # 开始事务 Query OK, 0 rows affected (0.00 sec) mysql> insert into runoob_transaction_test value(5); Query OK, 1 rows affected (0.01 sec) mysql> insert into runoob_transaction_test value(6); Query OK, 1 rows affected (0.00 sec) mysql> commit; # 提交事务 Query OK, 0 rows affected (0.01 sec) mysql> select * from runoob_transaction_test; +------+ | id | +------+ | 5 | | 6 | +------+ 2 rows in set (0.01 sec) mysql> begin; # 开始事务 Query OK, 0 rows affected (0.00 sec) mysql> insert into runoob_transaction_test values(7); Query OK, 1 rows affected (0.00 sec) mysql> rollback; # 回滚 Query OK, 0 rows affected (0.00 sec) mysql> select * from runoob_transaction_test; # 由于回滚因此数据没有插入 +------+ | id | +------+ | 5 | | 6 | +------+ 2 rows in set (0.01 sec)