JDBC系列:(7)使用Connection操作事务

事务ACID特性
序号 特性 描述
1 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2 一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
3 隔离性(Isolation) 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
4 持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
Connection操作事务的相关方法
序号 方法 作用
1 void setAutoCommit(boolean autoCommit) 设置事务是否自动提交
如果设置为false,表示手动提交事务。
2 void commit() () 手动提交事务
3 void rollback() 回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
4 Savepoint setSavepoint(String name) 在当前事务中创建一个保存点

1、使用事务

package com.rk.db.g_transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.rk.db.utils.JDBCUtil;

/**
 * // 转账,使用事务
 * @author RK
 *
 */
public class Demo01
{
	public static void main(String[] args)
	{
		Connection conn = null;
		try
		{
			conn = JDBCUtil.getConnection();
			// 1、设置事务为手动提交
			conn.setAutoCommit(false);

			boolean flag = true; //表示是否出现SQL异常
			transferMoney(conn, 100, "张三", "李四",flag);
		}
		catch (SQLException e)
		{
			System.out.println("转账失败!");
			try
			{
				// 2、 出现异常,需要回滚事务
				conn.rollback();
				System.out.println("回滚操作成功!!!");
			}
			catch (SQLException ex)
			{
				ex.printStackTrace();
			}
		}
		finally
		{
			// 3、所有的操作执行成功, 提交事务
			try
			{
				conn.commit();
				System.out.println("执行完毕!");
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
			JDBCUtil.closeQuietly(conn);
		}
	}

	/**
	 * 模拟银行转账
	 * @param conn 数据库连接
	 * @param moneyNum 转账的金额
	 * @param userAdd 收到Money的用户
	 * @param userSub 支出Money的用户
	 * @param flag 是否模拟SQL Exception异常,true表示出现,false表示不出现
	 * @throws SQLException
	 */
	private static void transferMoney(Connection conn, 
			long moneyNum, String userAdd, String userSub,
			boolean flag) throws SQLException
	{
		PreparedStatement pstmtAdd = null;
		PreparedStatement pstmtSub = null;

		try
		{
			String sqlAddMoney = "update T_Bank set money=money+? where username=?";
			pstmtAdd = conn.prepareStatement(sqlAddMoney);
			pstmtAdd.setLong(1, moneyNum);
			pstmtAdd.setString(2, userAdd);
			pstmtAdd.executeUpdate();

			if(flag)
			{
				throw new SQLException("模拟SQL执行出错");
			}

			String sqlSubMoney = "update T_Bank set money=money-? where username=?";
			pstmtSub = conn.prepareStatement(sqlSubMoney);
			pstmtSub.setLong(1, moneyNum);
			pstmtSub.setString(2, userSub);
			pstmtSub.executeUpdate();
		}
		finally
		{
			JDBCUtil.closeQuietly(pstmtAdd);
			JDBCUtil.closeQuietly(pstmtSub);
		}

	}
}

2、使用事务,回滚到指定的代码段

package com.rk.db.g_transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;

import com.rk.db.utils.JDBCUtil;

/**
 * // 转账,使用事务, 回滚到指定的代码段
 * @author RK
 *
 */
public class Demo02
{
	public static void main(String[] args)
	{
		Connection conn = null;
		Savepoint sp = null;
		try
		{
			conn = JDBCUtil.getConnection();
			// 1、设置事务为手动提交
			conn.setAutoCommit(false);

			transferMoney(conn, 1000, "李四", "张三",false);

			// 如果失败,回滚到这个位置
			sp = conn.setSavepoint();

			boolean flag = true; //表示是否出现SQL异常
			transferMoney(conn, 500, "张三", "李四",flag);
		}
		catch (SQLException e)
		{
			System.out.println("转账失败!");
			try
			{
				// 2、 出现异常,需要回滚 (回滚到指定的代码段)
				conn.rollback(sp);
				System.out.println("回滚到指定位置操作成功!!!");
			}
			catch (SQLException ex)
			{
				ex.printStackTrace();
			}
		}
		finally
		{
			// 3、所有的操作执行成功, 提交事务
			try
			{
				conn.commit();
				System.out.println("执行完毕!");
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
			JDBCUtil.closeQuietly(conn);
		}
	}

	/**
	 * 模拟银行转账
	 * @param conn 数据库连接
	 * @param moneyNum 转账的金额
	 * @param userAdd 收到Money的用户
	 * @param userSub 支出Money的用户
	 * @param flag 是否模拟SQL Exception异常,true表示出现,false表示不出现
	 * @throws SQLException
	 */
	private static void transferMoney(Connection conn, 
			long moneyNum, String userAdd, String userSub,
			boolean flag) throws SQLException
	{
		PreparedStatement pstmtAdd = null;
		PreparedStatement pstmtSub = null;

		try
		{
			String sqlAddMoney = "update T_Bank set money=money+? where username=?";
			pstmtAdd = conn.prepareStatement(sqlAddMoney);
			pstmtAdd.setLong(1, moneyNum);
			pstmtAdd.setString(2, userAdd);
			pstmtAdd.executeUpdate();

			if(flag)
			{
				throw new SQLException("模拟SQL执行出错");
			}

			String sqlSubMoney = "update T_Bank set money=money-? where username=?";
			pstmtSub = conn.prepareStatement(sqlSubMoney);
			pstmtSub.setLong(1, moneyNum);
			pstmtSub.setString(2, userSub);
			pstmtSub.executeUpdate();
		}
		finally
		{
			JDBCUtil.closeQuietly(pstmtAdd);
			JDBCUtil.closeQuietly(pstmtSub);
		}

	}
}
时间: 2024-10-29 19:09:53

JDBC系列:(7)使用Connection操作事务的相关文章

老调重弹:JDBC系列 之 <JDBC层次结构和基本构成>

前言 最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,老调重弹,好好总结一番,作为自己的笔记,也是给读者一个参考---本篇博文是我的上篇博文老调重弹:JDBC系列 之 <驱动加载原理全面解析>的续文,主要梳理一下JDBC的层次结构和基本构成.以下是本文的组织内容(用户可以点击上面的目录栏查看): JDBC的层次结构 总体而言,JDBC包含以下几大角色 : Driver.DriverMan

老调重弹:JDBC系列 之 存储过程 CallableStatement(创建和使用)

前言 最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,老调重弹,好好总结一番,作为自己的笔记,也是给读者一个参考--- 本文主要通过 使用JDBC创建存储过程 和使用JDBC调用存储过程两部分 阐述JDBC 对存储过程的支持.本文将在Oracle数据库下创建一个可以表示岗位信息的基本表Jobs为例, 然后通过存储过程对这个Jobs表进行各种操作.表JOBS的建表语句如下: -- Creat

JDBC、JTA、Spring的事务管理

Java事务的类型有三种:JDBC事务.JTA(Java Transaction API)事务.容器事务. 事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作.       这样可以防止出现脏数据,防止数据库数据出现问题.开发中为了避免这种情况一般都会进行事务管理. JDBC中是通过Connection对象进行事务管理的Hibernate中是通过Transaction进行事务管理,处理方法与JDBC

Oracle系列:(20)事务

回顾什么是事务? 一个不可分割的子操作形成一个整体,该整体要么全部执行成功,要么全部执行失败.例如:转帐 回顾为什么要用事务? 如果不用事务的话,为转帐为例,可能出现一个用户钱增加了,另一个用户钱不变 回顾编程中,事务可用于哪一层? 事务放在业务层 回顾jdbc编程中,如何使用事务? connection.setAutoCommit(false); pstmt.executeUpdate(); connection.commit(); connection.rollback(); 回顾hiber

老调重弹:JDBC系列 之 &lt;驱动加载原理全面解析&gt;

前言 最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者一个参考---以下是本文的组织结构,读者可以点击上面的目录查看: 概述 一般情况下,在应用程序中进行数据库连接,调用JDBC接口,首先要将特定厂商的JDBC驱动实现加载到系统内存中,然后供系统使用.基本结构图如下: 驱动加载入内存的过程 这里所谓的驱动,其实就是实现了java.sql.Driver

服务器用JDBC对mysql数据库进行操作

1:获取数据库连接 Connection connection=getConnection(); 2:准备SQL语句 3:调用Connection的creatStatement()方法获取Statement对象执行SQL语句 (注:Statement对象处理的SQL语句只能是INSERT,UPDATE或DELETE) statement=connection.createStatement(); statement.execute(SQL); 4:关闭Statement对象 5:关闭数据库连接

java jdbc深入理解(connection与threadlocal与数据库连接池和事务实)

1.jdbc连接数据库,就这样子 Class.forName("com.mysql.jdbc.Driver"); java.sql.Connection conn = DriverManager.getConnection(jdbcUrl); 2.通过传入jdbc url用Drivermanager.getConnection(jdbcurl)连接数据库, 注意:一次Drivermanager.getConnection(jdbcurl)获得只是一个connection,并不能满足高并

【j2ee spring】7、spring与数据库的连接的操作事务管理

spring与数据库的连接的操作事务管理 1.首先我们的知道spring管理事务的方式有两种 还是一种是以注解的方式 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚.这个例外是unchecked 如果遇到checked意外就不回滚. 1 让checked例外也回滚:在整个方法前加上 @Transactional(rollb

老调重弹:JDBC系列之&lt;驱动加载原理全面解析) ----转

  最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者一个参考--- 概述 一般情况下,在应用程序中进行数据库连接,调用JDBC接口,首先要将特定厂商的JDBC驱动实现加载到系统内存中,然后供系统使用.基本结构图如下: 驱动加载入内存的过程 这里所谓的驱动,其实就是实现了java.sql.Driver接口的类.如oracle的驱动类是 oracle.j