<十一>JDBC_事务的处理+隔离






Tom给jerry汇款500元
1、如果多个操作,每个操作使用的是自己的单独的连接,则无法保证事务
2、具体步骤:
1>事务开始操作前,开始事务:取消Connection的默认提交行为
2>如果事务的操作都成功,都提交事务
3>回滚事务:若出现异常,则在catch块中回滚事务;
3、模板 try {
//开始事务:取消默认提交(默认自动提交) con.setAutoCommit(false);
//...
//提交事务 con.commit();
} catch (Exception e) {
//...
//如果出现异常就回滚事
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
@Test
public void testTransaction() {
Connection con = null;
try {
con = JDBCTools.getConnection();
System.out.println("默认事务:" + con.getAutoCommit());
// 开始事务:取消默认提交(默认自动提交)
con.setAutoCommit(false);
String sql = "update users set balance=balance-500 where id=1";
update(con, sql);
int i = 10 / 0;
sql = "update users set balance=balance+500 where id=2";
update(con, sql);
// 提交事务
con.commit();
} catch (Exception e) {
// 如果出现异常就回滚事务
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
JDBCTools.release(null, null, con);
}
}
设置事务的隔离级别
@Test
public void testTransactionIsolationRead() {
String sql = "select balance from users where id=1";
Integer balance=getForValue(sql);
System.out.println("balance="+balance);
}
/*
* 测试事务的隔离级别 在JDBC程序中可以通过Connection的setTransactionIsolation()方法 来设置事务的隔离级别
*/
@Test
public void testTransactionIsolationUpdate() {
Connection con = null;
try {
con = JDBCTools.getConnection();
// 开始事务:取消默认提交(默认自动提交)
con.setAutoCommit(false);
String sql = "update users set balance=balance-500 where id=1";
update(con,sql);
con.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
// 返回某个对象的属性值
@SuppressWarnings("unchecked")
public <E> E getForValue(String sql, Object... args) {
// 1、得到结果集:该结果集应该只有一行且只有一列
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = JDBCTools.getConnection();
//con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
ps = con.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
if (rs.next()) {
return (E) rs.getObject(1);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(rs, ps, con);
}
// 2、取得结果集的
return null;
}
更新后的JDBCTools.java工具类如下:
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/*
* JDBC工具类
* */
public class JDBCTools {
// 提交事务
public static void commit(Connection con) {
if (con != null) {
try {
con.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//回滚事务
public static void rollback(Connection con) {
if (con != null) {
try {
con.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//开始事务
public static void beginTx(Connection con) {
if (con != null) {
try {
con.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/*
* 执行SQL的方法 insert,update,delete
*/
public static void update(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
try {
/*
* 1、获取Connection连接 2、获取Statement 3、SQL语句 4、关闭数据库连接
*
*/
conn = getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
release(null, ps, conn);
}
}
public static Connection getConnection() throws Exception {
String driverClass = null;
String jdbcUrl = null;
String user = null;
String password = null;
// 读取类路径下的jdbc.properties文件
InputStream in = JDBCTools.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(in);
driverClass = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password");
// 加载数据库驱动程序
Class.forName(driverClass);
// 通过DriverManager的getConnection()方法获取数据库连接
Connection connection = DriverManager.getConnection(jdbcUrl, user, password);
return connection;
}
public static void release(ResultSet rs, Statement st, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
<十一>JDBC_事务的处理+隔离的更多相关文章
- 深入解析Mysql中事务的四大隔离级别及其所解决的读现象
本文详细介绍四种事务隔离级别,并通过举例的方式说明不同的级别能解决什么样的读现象.并且介绍了在关系型数据库中不同的隔离级别的实现原理. 在DBMS中,事务保证了一个操作序列可以全部都执行或者全部都不执 ...
- Spring事务传播机制&隔离级别
一.Propagation (事务的传播属性) Propagation : key属性确定代理应该给哪个方法增加事务行为.这样的属性最重要的部份是传播行为.有以下选项可供使用:PROPAGATION_ ...
- 数据库事务中的隔离级别和锁+spring Transactional注解
数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...
- Spring事务传播、隔离等级
事务传播 PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中.这是最常见的选择. PROPAGATION_SUPPORTS 支持当前事 ...
- mysql事务之间的隔离级别
事务间未做隔离,会引起下面这些问题. 1.脏读:一个事务可读到另外一个尚未commit的事务中的数据. 2.不可重复读:在一个事务中,读取同一个数据 a,b,按顺序读取,在读a b 之间,另外一个事 ...
- MySQL 笔记整理(8.b) --事务到底是隔离还是不隔离的?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 8.a) --事务到底是隔离还是不隔离的? 本周工作较忙,加上懒惰,拖更 ...
- MySQL 笔记整理(8.a) --事务到底是隔离还是不隔离的?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 8.a) --事务到底是隔离还是不隔离的? 这部分内容不太容易理解,笔者也是进行了多次阅读.因此引用原文: 之前有提到过,如果是在可 ...
- 数据库事务的四大特性以及事务的隔离级别-与-Spring事务传播机制&隔离级别
数据库事务的四大特性以及事务的隔离级别 本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
随机推荐
- Target runtime com.genuitec.runtime.generic.jee60 is not defined
转载自:http://jingyan.baidu.com/article/d7130635338e3f13fdf47518.html 用eclipse加载别人的工程,报错Target runtime ...
- DOS批处理命令
1.echo的用法(echo /? --查看帮助) echo off/on 打开关闭回显功能(@echo off 关闭回显并且不需要回显 echo 命令) echo, 显示空行(也可以是; . ...
- RecyclerView解密篇(二)
在上一篇(RecyclerView解密篇(一))文章中简单的介绍了RecyclerView的基本用法,接下来要来讲讲RecyclerView的更多用法,要实现不同的功能效果,大部分都还是在于Recyc ...
- C# winform 跨线程更改窗体控件的属性
当winform程序中新开一个线程,是无法改变主线程中窗体控件的属性的,否则运行时会报错. 若想在其他线程中控制主线程中的窗体控件,则必须利用BeginInvoke方法. 例如:添加一个名为textb ...
- linux下误删mysql的root用户,解决方法
开始对liunx界面不熟悉,可能由于不小心,把root误删了,怎么办? 1. # killall mysqld 干掉所有mysql进程 2. # mysqld_safe --skip-grant ...
- JavaScript 学习笔记——cssText
平常编写代码,更改一个元素样式的时候,自己都是用 obj.style.width = "200px"; obj.style.position = "absolute&qu ...
- MySQL Fabric和MyBatis的整合过程中遇到的问题
这是我昨天在整合MySQL Fabric和MyBatis时遇到的问题,花了大半天才解决的问题,解决的过程中在网上查找了很久,都没有找到解决的方案.现在记下来,希望能够帮助有同样问题的朋友.如果各位朋友 ...
- MFC注册窗口类以及FindWindow按窗口类名查询
很多玩游戏的人都知道一般游戏客户端程序是不允许双开的,就是说在同一游戏在启动的时候,是无法打开多个窗口.很多其他软件如酷狗播放器等也是这样.如果把打开的窗口最小化,这时重新启动程序,最小化的窗口会被显 ...
- cout 格式化输出
一直习惯于C语言的printf函数来打印,突然有一天要用cout来打印,发现有点不适应. 原来cout也是有格式化输出的. 首先要引入头文件 #include<iostream> // 在 ...
- 【转】linux sort 命令详解
sort是在Linux里非常常用的一个命令,管排序的,集中精力,五分钟搞定sort,现在开始! 1 sort的工作原理 sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按AS ...