1. 事务

在关系型数据库中,有一个很重要的概念,叫做事务(Transaction)。它具有 ACID 四个特性:

  • A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
  • C(Consistency):一致性,事务必须是使数据库从一个一致性状态变到另一个一致性状态。
  • I(Isolation):隔离性,一个事务的执行不能被其他事务干扰。
  • D(Durability):持久性,,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

2. JDBC 的事务支持

在 JDBC 学习笔记(三)—— JDBC 常用接口和类,JDBC 编程步骤,我曾经提及,JDBC 是使用 Connection 来控制事务的。

Connection 默认使用自动提交策略,即关闭事务,这种情况下,每一条 SQL 语句一旦执行,就会立即提交到数据库,无法回滚。

Connection 提供了以下三个事务相关的接口:

// 关闭自动提交,开启事务
void setAutoCommit(boolean autoCommit) throws SQLException; // 提交事务
void commit() throws SQLException; // 回滚事务
void rollback() throws SQLException;

setAutoCommit(boolean autoCommit) 方法其实做了两件事情:

  • 更改提交策略
  • 开启事务
commit() 方法负责将一个事务内部的所有 SQL 语句一次性提交(全部执行,或者全部不执行)。
rollback() 方法负责回滚事务。
 
对于 rollback,有一点需要特别注意,如果系统遇到一个未处理的 SQLException,程序会自动回滚;反之,如果这个异常被捕获,则需要手动回滚。
 
例如,以下写法无需手动回滚:
try (Connection conn = Connector.getSqlConnection()) {
  conn.setAutoCommit(false);
  try (Statement stmt = conn.createStatement()) {
    stmt.executeUpdate(sql1);
    stmt.executeUpdate(sql2);
  }
  conn.commit();
} catch (SQLException e) {
  e.printStackTrace();

而以下写法则不会自动回滚:

try (Connection conn = Connector.getSqlConnection()) {
conn.setAutoCommit(false);
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(sql1);
stmt.executeUpdate(sql2);
} catch (SQLException e1) {
e1.printStackTrace();
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}

3. Savepoint

JDBC 另外提供了一个 Savepoint 接口,用来实现事务部分提交。

有时候,我们并不希望一个事务全部执行,或者全部不执行,可能会有这样的需求:

如果执行到某一步出错,回滚的时候返回之前开启事务之后的某一个点。

这时候就需要 Savepoint(这个和 Hiberbate 的隔离级别很类似)。

通过以下示例代码,在执行 sql3 的时候出错,但是由于在执行完 sql1 的时候使用了 Savepoint,所以第一条 SQL 语句的执行结果会保留到数据库中:

package com.gerrard.demo;

import com.gerrard.util.Connector;
import com.gerrard.util.DriverLoader; import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement; public final class SavePointDemo { public static void main(String[] args) {
String sql1 = "INSERT INTO STUDENT (STUDENT_NAME, STUDENT_PASSWORD) VALUES ('Ramsey', '999999')";
String sql2 = "INSERT INTO STUDENT (STUDENT_NAME, STUDENT_PASSWORD) VALUES ('Wilshere', '888888')";
// Invalidate SQL
String sql3 = "INSERT INTO STUDENT VALUES(1, 'Ramsey', '999999')"; DriverLoader.loadSqliteDriver();
try (Connection conn = Connector.getSqlConnection()) {
conn.setAutoCommit(false);
Savepoint save1 = null;
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(sql1);
save1 = conn.setSavepoint();
stmt.executeUpdate(sql2);
stmt.executeUpdate(sql3);
} catch (SQLException e) {
conn.rollback(save1);
}
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

最新文章

  1. git stash和git stash pop
  2. WdatePicker 没有权限 不能执行已释放 Script 的代码
  3. Tomcat 启动项目报错 java.lang.OutOfMemoryError: Java heap space
  4. SQL Server 文件和文件组
  5. 使用mysql服务来记录用户的反馈
  6. android学习笔记---发送状态栏通知
  7. struts2标签具体解释
  8. js prototype __proto__ instanceof constructor
  9. Andriod布局之LinearLayout
  10. ##DAY3 自定义视图、视图控制器、视图控制器指定视图、loadView、 viewDidLoad、MVC、屏幕旋转、内存警告
  11. SSIS 连接 PostgreSQL
  12. Nginx之http_image_filter_module模块使用
  13. Array(数组)的使用
  14. 论MySQL何时使用索引,何时不使用索引
  15. jquery+ajax搜索并分页
  16. Centos 7安装RabbitMQ 3.7.8版本(单机版)-不使用RPM
  17. JS膏集04
  18. CM记录-操作系统调优
  19. MVC简介与三层架构
  20. urb传输的代码分析【转】

热门文章

  1. iOS 提交form表单,上传图片
  2. 如果int x=20, y=5,则语句System.out.println(x+y +""+(x+y)+y); 的输出结果是()
  3. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第八节
  4. 面向对象编程 -------JavaScrip
  5. windows下安装win7虚拟机并安装oracle
  6. css分层,实现遮罩底层弹出新窗口里可以操作,最下层能看到单不能操作
  7. linux普通文件权限和系统目录权限的实践及结论
  8. 关于 composer 的一些坑
  9. Python之路-基础数据类型之字符串
  10. Xadmin后台管理系统搭建基于Django1.11.11+Python3.6