使用了持久化框架几乎没有使用过原生的jdbc API ,发现原来使用jdbc API来实现事务也是很简单的。

数据库的链接connection具有一个属性autocommit,这个属性默认是true,作用是控制是否把执行的命令提交给数据库。一旦命令被提交就无法回滚数据库。

而我们实现事务的方式也是很简单,就是手动设置属性autocommit的值为false,等执行完全部命令之后再手动提交所有命令就可以了。

try (Connection connection = DriverManager.getConnection(url, username, password)) {
System.out.println("数据库链接成功!"); try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
String command = "insert into a_dept(name) values('1'),('2')";
int count = statement.executeUpdate(command);
System.out.println("受影响行数:" + count); String selectSql = "select * from a_dept";
String updateSql = "update a_dept set name=? where id=?";
String insertSql = "insert into a_dept(name) values(?)";
try (ResultSet resultSet = statement.executeQuery(selectSql)) {
while (resultSet.next()) {
System.out.print("修改前id " + resultSet.getInt("id") + "的值是: ");
System.out.println(resultSet.getString("name"));
}
resultSet.beforeFirst();
connection.setAutoCommit(false);
while (resultSet.next()) {
PreparedStatement updateState = connection.prepareStatement(updateSql);
updateState.setString(1, "I am new" + resultSet.getInt("id"));
updateState.setInt(2, resultSet.getInt("id"));
updateState.executeUpdate();
} // Savepoint savepoint = connection.setSavepoint();
PreparedStatement updateState = connection.prepareStatement(insertSql);
updateState.setString(1, "我是插入的");
updateState.executeUpdate();
try {
PreparedStatement updateStateFail = connection.prepareStatement(insertSql);
updateStateFail.setString(1, "我是插入的,但是我太长了,所以我是插不进去的,会报错!");
updateStateFail.executeUpdate(); } catch (Exception e) {
connection.rollback();
System.err.println(e.getMessage());
}
connection.commit();
Statement newStatement = connection.createStatement();
ResultSet newSet = newStatement.executeQuery(selectSql);
System.out.println("打印出所有的值:");
while (newSet.next()) {
System.out.print(newSet.getInt("id") + ": ");
System.out.println(newSet.getString("name"));
}
}
}
}

  贴运行结果:

红色字体就是报错的信息。我们可以发现,在这个结果集当中没有进行修改,也没有进行插入,所有的修改和插入命令因为插入操作的错误都被回滚了。

但是我们发现我们的修改操作和插入操作都被回滚了,这在一些情况下我们不希望所有的操作都被回滚,那么我们可以设置回滚的节点,设置回滚的节点也很简单,在想要的地方添加如下代码,

Savepoint savepoint = connection.setSavepoint();

那么就会在该地生成一个节点,回滚把这个节点作为参数传递给回滚的方法 rollback() ,那么回滚的时候会放过该节点之前的操作,需要注意的是节点使用完之后必须释放它。

结果如下(不要在意Id亲,我清了数据库了):
Connected to the target VM, address: '127.0.0.1:17576', transport: 'socket'
数据库链接成功!
受影响行数:2
修改前id 479的值是: 1
修改前id 480的值是: 2
Data truncation: Data too long for column 'name' at row 1
打印出所有的值:
479: I am new479
480: I am new480
Disconnected from the target VM, address: '127.0.0.1:17576', transport: 'socket'

简单吧:

最后附上使用节点回滚的全部代码,可以不看~:

        try (Connection connection = DriverManager.getConnection(url, username, password)) {
System.out.println("数据库链接成功!"); try (Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
String command = "insert into a_dept(name) values('1'),('2')";
int count = statement.executeUpdate(command);
System.out.println("受影响行数:" + count); String selectSql = "select * from a_dept";
String updateSql = "update a_dept set name=? where id=?";
String insertSql = "insert into a_dept(name) values(?)";
try (ResultSet resultSet = statement.executeQuery(selectSql)) {
while (resultSet.next()) {
System.out.print("修改前id " + resultSet.getInt("id") + "的值是: ");
System.out.println(resultSet.getString("name"));
}
resultSet.beforeFirst();
connection.setAutoCommit(false);
while (resultSet.next()) {
PreparedStatement updateState = connection.prepareStatement(updateSql);
updateState.setString(1, "I am new" + resultSet.getInt("id"));
updateState.setInt(2, resultSet.getInt("id"));
updateState.executeUpdate();
} Savepoint savepoint = connection.setSavepoint();
PreparedStatement updateState = connection.prepareStatement(insertSql);
updateState.setString(1, "我是插入的");
updateState.executeUpdate();
try {
PreparedStatement updateStateFail = connection.prepareStatement(insertSql);
updateStateFail.setString(1, "我是插入的,但是我太长了,所以我是插不进去的,会报错!");
updateStateFail.executeUpdate(); } catch (Exception e) {
connection.rollback(savepoint);
               connection.releaseSavepoint(savepoint);
System.err.println(e.getMessage());
}
connection.commit();
Statement newStatement = connection.createStatement();
ResultSet newSet = newStatement.executeQuery(selectSql);
System.out.println("打印出所有的值:");
while (newSet.next()) {
System.out.print(newSet.getInt("id") + ": ");
System.out.println(newSet.getString("name"));
}
}
}
}

  

JDBC API 事务的实践的更多相关文章

  1. JDBC、事务和连接池

    一:JDBC 1.什么是JDBC JDBC(Java Data Base Connectivity)SUN公司提供的一套操作数据库的标准规范.具体来讲是一种用于执行SQL语句的Java API,为多种 ...

  2. [疯狂Java]JDBC:事务管理、中间点、批量更新

    1. 数据库事务的概念:     1) 事务的目的就是为了保证数据库中数据的完整性.     2) 设想一个银行转账的过程,假设分两步,第一步是A的账户-1000,第二步是B的账户+1000.这两个动 ...

  3. 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例

    Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...

  4. Spring中的JDBC API

    1 JdbcTemplate的诞生 JDBC作为Java平台访问关系数据库的标准API,其成功是有目共睹的.为了避免在JDBC API在使用中的种种尴尬局面(几乎程式一样的代码,繁琐的异常处理),Sp ...

  5. JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务

    JDBC基础 重难点梳理 一.JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以 ...

  6. Spring框架——JDBC与事务管理

    JDBC JDBCTemplate简介 XML配置JDBCTemplate 简化JDBC模板查询 事务管理 事务简介 Spring中的事务管理器 Spring中的事务管理器的不同实现 用事务通知声明式 ...

  7. RESTful API 设计最佳实践

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...

  8. JDBC API Description

    package java.sql description What the JDBCTM 4.2 API Includes Versions What the java.sql Package Con ...

  9. Spring总结——AOP、JDBC和事务的总结

    1.上一次总结了 Spring 的核心三大组件(Core,Beans,Context),今天总结的 AOP.JDBC和事务都可以看成是核心三大组件的应用. 其中 Spring 的事务管理又以 AOP ...

随机推荐

  1. cacti报警邮件的设置

    众所周知,用Linux系统自带的sendmail发送邮件是有限制的,可能对有些邮箱无法正常发送,导致报警邮件不能够及时发送到,因此就可能会产生不必要的麻烦!对此,我们可以用其他方法来发送邮件,就是在c ...

  2. [Luogu P1516]青蛙的约会

    按照题意,显然可以列出同余方程,k即为所求天数,再将其化为不定方程 ,那么对这个方程用扩展欧几里德算法即可得出k,q的一组解,但是方程有解的充要条件是(m – n) 和L不同时为零并且x – y是m ...

  3. [物理学与PDEs]第2章第2节 粘性流体力学方程组 2.2 应力张量

    1.  在有粘性的情形, 外界流体对 $\Omega$ 的作用力, 不仅有表面上的压力 (正压力), 也有表面上的内摩擦力 (切应力). 2.  于 $M$ 处以 ${\bf n}$ 为法向的单位面积 ...

  4. 基于vue cli 3.0创建前端项目并安装cube-ui

    前提条件: 安装node.js. 国内的开发者最好先配置淘宝镜像. 之后用cnpm来代替npm命令. 项目创建过程: 打开cmd,输入命令进入目标工作空间,以本机项目为例: cd /d d: cd D ...

  5. JMX的l理解

    一.JMX的一些定义与用途 Java Management Extensions:Java管理扩展,是管理系统和资源之间的一个接口,它定义了管理系统和资源之间交互的标准. 1.专门管理,监控jvm的一 ...

  6. Wndows下Apache+php+Mysql环境的搭建及其涉及的知识(转)

    一.安装Apache 1. 在网上搜索以下3个文件,以及找一个地方新建一个文件夹 好吧,这里有下载链接:http://pan.baidu.com/s/1hr9IdSS 文件夹内有:apache,mys ...

  7. Django跨域请求

    一.jsonp方式 同源策略会阻止ajaxa请求,但不阻止src. jsonp方式其实是利用了<script>标签可以直接跨域的性质,在body中生成一个<script>标签, ...

  8. SQL Server - 四种排序, ROW_NUMBER() /RANK() /DENSE_RANK() /ntile() over()

    >>>>英文版 (更简洁易懂)<<<< 转载自:https://dzone.com/articles/difference-between-rownum ...

  9. sqlserver 迁移

    背景 好久没用sqlserver了,好多东西也都记不住了,这次sqlserver同事问了几个问题,也一就回忆下.主要也把sqlserver的迁移过程列下.具体就不多说了. sqlserver 特点是只 ...

  10. C# 微信开发-----微信会员卡(三)激活会员卡

    在会员领取了会员卡之后需要做 一个跳转性激活,模式请看下图: 在创建会员卡的时候需要配置下这个参数的值: memberActivate.aspx页面代码如下: <%@ Page Language ...