JDBC API 事务的实践
使用了持久化框架几乎没有使用过原生的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 事务的实践的更多相关文章
- JDBC、事务和连接池
一:JDBC 1.什么是JDBC JDBC(Java Data Base Connectivity)SUN公司提供的一套操作数据库的标准规范.具体来讲是一种用于执行SQL语句的Java API,为多种 ...
- [疯狂Java]JDBC:事务管理、中间点、批量更新
1. 数据库事务的概念: 1) 事务的目的就是为了保证数据库中数据的完整性. 2) 设想一个银行转账的过程,假设分两步,第一步是A的账户-1000,第二步是B的账户+1000.这两个动 ...
- 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例
Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...
- Spring中的JDBC API
1 JdbcTemplate的诞生 JDBC作为Java平台访问关系数据库的标准API,其成功是有目共睹的.为了避免在JDBC API在使用中的种种尴尬局面(几乎程式一样的代码,繁琐的异常处理),Sp ...
- JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务
JDBC基础 重难点梳理 一.JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以 ...
- Spring框架——JDBC与事务管理
JDBC JDBCTemplate简介 XML配置JDBCTemplate 简化JDBC模板查询 事务管理 事务简介 Spring中的事务管理器 Spring中的事务管理器的不同实现 用事务通知声明式 ...
- RESTful API 设计最佳实践
背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...
- JDBC API Description
package java.sql description What the JDBCTM 4.2 API Includes Versions What the java.sql Package Con ...
- Spring总结——AOP、JDBC和事务的总结
1.上一次总结了 Spring 的核心三大组件(Core,Beans,Context),今天总结的 AOP.JDBC和事务都可以看成是核心三大组件的应用. 其中 Spring 的事务管理又以 AOP ...
随机推荐
- Matlab怎么修改显示数值格式/精度/小数位数
参考:https://jingyan.baidu.com/article/7f41ecec1ad029593c095c70.html
- Git 分支 (三) 分支管理&&分支开发工作流
分支管理 git branch 命令不只是可以创建与删除分支. 如果不加任何参数运行它,会得到当前所有分支的一个列表: 注意 master 分支前的 * 字符:它代表现在检出的那一个分支(也就是说,当 ...
- Entity Framework入门教程(6)--- 在线场景中保存数据
在线场景中保存数据 在线场景中保存实体数据是一项相当容易的任务,因为使用的是同一个context,这个context会自动跟踪所有实体发生的更改. 下图说明了在线场景中的CUD(创建,更新,删除)操作 ...
- oldboy s21day10
#!/usr/bin/env python # -*- coding:utf-8 -*- # 1.写函数,函数可以支持接收任意数字(位置传参)并将所有数据相加并返回. ''' def func(* ...
- css中font-size为0的妙用(消除内联元素间的间隔)
前言 <div> <input type="text"> <input type="button" value="提交& ...
- Spark 用户自定义函数 Java 示例
Spark UDF Java 示例 在这篇文章中提到了用Spark做用户昵称文本聚类分析,聚类需要选定K个中心点,然后迭代计算其他样本点到中心点的距离.由于中文文字分词之后(n-gram)再加上昵称允 ...
- [物理学与PDEs]第4章第3节 一维反应流体力学方程组 3.3 一维反应流体力学方程组的数学结构
一维理想反应流体力学方程组是一阶拟线性双曲组.
- [物理学与PDEs]第1章第2节 预备知识 2.1 Coulomb 定律, 静电场的散度与旋度
1. Coulomb 定律, 电场强度 (1) 真空中 $P_1$ 处有电荷 $q_1$, $P$ 处有电荷 $q$, ${\bf r}_1=\vec{P_1P}$, 则 $q$ 所受的力为 $$\b ...
- Chrome 禁止从页面打开 Data URI 网址了
现如今,网民的网络账户被盗,很有可能是被“钓鱼”了.去年的一份安全报告中指出:“近85%的资金损失是通过钓鱼网址泄露支付信息造成的”. 传统的钓鱼网站通常是申请一个和被冒充网站相似的域名,比如 tao ...
- [转] fastText
mark- from : https://www.jiqizhixin.com/articles/2018-06-05-3 fastText的起源 fastText是FAIR(Facebook AIR ...