当我们在JDBC程序中向数据库获取一个Connection对象时,在默认情况下这个Connection对象会自动向数据库提交当下所执行的sql语句,但我们在某些情况想要将多条sql语句同时提交的话,我们就要将所执行的多条sql语句放在事务当中同时执行
事务的四大特性:
a:原子性:是数据库中最小的逻辑工作单元,对其数据修改,要么全部执行要么全部不执行.
b:一致性:事务在完成时,必须是所有的数据都保持一致的状态.
c:隔离性:一个事务的执行过程中,不能被其他事务所干扰.事物之间是相互隔离的.
d:持久性:一个事务一旦提交,事务的操作便永久的保存在数据库中.即使此时再执行回滚操作也不能撤销所做的更改.
例如在银行转账的例子能够清楚的体现事务的重要性.
String sql1="update bank set money=money-100 where username='李四'";
String sql2="update bank set money=money+100 where username='张三'";
我们可以看到银行的两个用户张三,李四的存取操作必须同时进行,此时我们就要将这两条sql语句放在事务中执行.
我们在对事务的编写也要掌握一定的顺序;
1:首先我们必须将事务的默认自动提交关闭将其默认值设置为false;
conn.setAutoCommit(false);
2:接下来我们要设置回滚点,当处理事务出现异常时,将数据回滚到未执行sql语句的状态,这样就会避免程序异常带来的麻烦.
setSavepoint = conn.setSavepoint();
3:将添加事务的sql语句放在try….catch 语句中
4:然后在catch语句中编写回滚语句,当执行事务当中出现异常时,将数据回滚到回滚点.
conn.rollback(setSavepoint);
5:最后在finally代码块中提交事务,(这个的前提是整个操作中无异常时)
conn.commit();
6:最终释放掉资源,这个事务就算编写完成.
示例代码:
package JDBC_Utils_demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
public class JDBC_test1_sw {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement statement1 = null;
PreparedStatement statement2 = null;
Savepoint setSavepoint = null;
try {
// 1:获取链接对象
conn = Utils.getconnection();
// 2:开启事务,将数据自动提交关闭
conn.setAutoCommit(false);
// 3:设置回滚点
setSavepoint = conn.setSavepoint();
// 4:定义sql语句
String sql1 = "update bank set money=money-100 where username='李四'";
String sql2 = "update bank set money=money+100 where username='张三'";
statement1 = conn.prepareStatement(sql1);
statement1.executeUpdate();
//当执行完第一条sql语句的时候,在这里我们设置了一个异常
System.out.println(1 / 0);
statement2 = conn.prepareStatement(sql2);
statement2.executeUpdate();
} catch (Exception e) {
try {
//如果出现异常,回滚到设置的回滚点
conn.rollback(setSavepoint);
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
try {
// 没有异常出现的时候,提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
try {
//最后调用工具类,释放资源.
Utils.close(conn, statement1);
} catch (SQLException e) {
e.printStackTrace();
}
try {
Utils.close(conn, statement2);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
执行完上述代码,我们在数据库中的bank表的数据在出现异常的情况下就不会改变.