JDBC高级开发事务

爱⌒轻易说出口 提交于 2019-12-11 04:32:30

一、事务管理

1.事务概述

事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败。
事务作用:保证在一个事务中多次操作,要么全都成功,要么全部失败。
一组:无论多少SQL语句,必须使用同一个连接对象操作,包括insert,update,delete,不包括select,因为select不改变原有数据

2.mysql事务操作

sql语句 描述
start transaction; 开启事务
commit; 提交事务
rollback; 回滚事务

准备数据

# 创建一个表:账户表.
create database webdb;
# 使用数据库
use webdb;
# 创建账号表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
# 初始化数据
insert into account values (null,'jack',10000);
insert into account values (null,'rose',10000);
insert into account values (null,'tom',10000);

操作:
MySQL中可以有两种方式进行事务的管理:
自动提交:MySQL默认自动提交。即执行一条sql语句提交一次事务。
手动提交:先开启,再提交
 方式1:手动提交

start transaction;
update account set money=money-1000 where name='jack';
update account set money=money+1000 where name='rose';
commit;
#或者
rollback;

 方式2:自动提交,通过修改mysql全局变量“autocommit”进行控制
在这里插入图片描述

show variables like '%commit%';
* 设置自动提交的参数为OFF:
set autocommit = 0;  -- 0:OFF  1:ON

扩展:Oracle数据库事务不自动提交

3.JDBC事务操作

Connection对象的方法名 描述
conn.setAutoCommit(false) 开启事务
conn.commit() 提交事务
conn.rollback() 回滚事务
//事务模板代码
public void demo01() throws SQLException{
	// 获得连接
	Connection conn = null;
	
	try {
		//#1 开始事务
		conn.setAutoCommit(false);
		
		//.... 加钱 ,减钱
		
		//#2 提交事务
		conn.commit();
	} catch (Exception e) {
		//#3 回滚事务
		conn.rollback();
	} finally{
		// 释放资源
		conn.close();
	}
}

4.DBUtils事务操作

Connection对象的方法名 描述
conn.setAutoCommit(false) 开启事务
new QueryRunner() 创建核心类,不设置数据源(手动管理连接)
query(conn,sql,handler,params)或update(conn,sql,params) 手动传递连接
DbUtils.commitAndClose(conn) 提交并关闭连接
DbUtils.rollbackAndClose(conn) 回滚并关闭连接

二、案例分析

在这里插入图片描述
开发中,常使用分层思想
不同的层次结构分配不同的解决过程,各个层次间组成严密的封闭系统
不同层级结构彼此平等
分层的目的是:
 解耦
 可维护性
 可扩展性
 可重用性
不同层次,使用不同的包表示
 com.baidu—— 公司域名倒写
 com.baidu.dao—— dao层
 com.baidu.service—— service层
 com.baidu.domain—— javabean
 com.baidu.utils—— 工具

三、代码实现

编写AccountService

public class AccountService {

	/**
	 * 业务层转账的方法:
	 * @param outUser	:付款人
	 * @param inUser	:收款人
	 * @param money	:转账金额
	 */
	public void transfer(String outUser, String inUser, int money) {
		// 调用DAO:
		AccountDao accountDao = new AccountDao();
		try {
			accountDao.outMoney(outUser, money);
			// int d = 1/0;
			accountDao.inMoney(inUser, money);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
}

编写AccountDao

public class AccountDao {

	/**
	 * 付款的方法
	 * @param name
	 * @param money
	 * @throws SQLException 
	 */
	public void outMoney(String name,int money) throws SQLException{
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			// 获得连接:
			conn = JDBCUtils.getConnection();
			// 编写一个SQL:
			String sql = "update account set money = money-? where name=?";
			// 预编译SQL:
			pstmt = conn.prepareStatement(sql);
			// 设置参数:
			pstmt.setInt(1, money);
			pstmt.setString(2, name);
			// 执行SQL:
			pstmt.executeUpdate();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			pstmt.close();
			conn.close();
		}
	}
	
	/**
	 * 收款的方法
	 * @param name
	 * @param money
	 * @throws SQLException 
	 */
	public void inMoney(String name,int money) throws SQLException{
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			// 获得连接:
			conn = JDBCUtils.getConnection();
			// 编写一个SQL:
			String sql = "update account set money = money+? where name=?";
			// 预编译SQL:
			pstmt = conn.prepareStatement(sql);
			// 设置参数:
			pstmt.setInt(1, money);
			pstmt.setString(2, name);
			// 执行SQL:
			pstmt.executeUpdate();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			pstmt.close();
			conn.close();
		}		
	}
}

四、事务管理:传递Connection

修改service和dao,service将connection传递给dao,dao不需要自己获得连接
在这里插入图片描述
service层

public void transfer(String outUser,String inUser,int money){
	Connection conn = null;
	try{
		//1获取连接
		conn = JdbcUtils.getConnection();
		//2开启事务
		conn.setAutoCommit(false);
		accountDao.outMoney(conn,outUser,money);
		accountDao.outMoney(conn,outUser,money);
		//3提交事务
		conn.commit();
	}catch(Exception e){
		try{
			//回滚
			if(conn != null){
				conn.rollback();
			}catch(Exception e2){
			}
			throw new RuntimeException(e);
		}finally{
			JdbcUtils.closeResource(conn,null,null);
		}
	}
}

dao层

/**
	 * 汇款
	 * @param outUser 汇款人 
	 * @param money -
	 */
public void outMoney(Connection conn,String outUser,int money){
	//Connection conn = null;
	PreparedStatement psmt = null;
	ResultSet rs = null;
	try{
		//1获取连接
		//conn = JdbcUtils.getConnection();
		//2准备sql语句
		String sql = "update account set money = money - ? where username = ?";
		//3预处理
		psmt = conn.prepareStatement(sql);
		//4设置实际参数
		psmt.setInt(1,money);
		psmt.setString(2,outUser);
		//5执行
		int r = psmt.executeUpdate();
		System.out.println(r);
	}catch (Exception e){
		throw new RuntimeException(e);
	}finally{
		//6释放资源
		JdbcUtils.closeResource(null,psmt,rs);
	}
}
/**
	 * 收款
	 * @param inUser 收款人
	 * @param money +
	 */
public void inMoney(Connection conn,String inUser , int money){
		//Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		try {
			//1 获得连接
			//conn = JdbcUtils.getConnection();
			//2 准备sql语句
			String sql = "update account set money = money + ? where username = ?";
			//3预处理
			psmt = conn.prepareStatement(sql);
			//4设置实际参数
			psmt.setInt(1, money);
			psmt.setString(2, inUser);
			//5执行
			int r = psmt.executeUpdate();
			System.out.println(r);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally{
			//6释放资源
			JdbcUtils.closeResource(null, psmt, rs);
		}
	}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!