jdbc事务连接管理-三层思想

代码仓库+教程文档:https://gitee.com/DerekAndroid/jdbcTransfer.git 

/**
 * 案例:使用三层思想实现转账
 * 
 * 1.事务: 是逻辑上的一组操作(多个sql语句),要么都成功 要么都失败
 * 
 * 
 * 2.事务的操作:
 * 		开启事务:
 * 			java程序代码: 连接对象.setAutoCommit(false);
 * 			 DOS窗口代码: start transaction;
 * 		提交事务
 * 			java代码:连接对象.commit();
 * 			DOS窗口代码:commit;
 * 		回滚事务
 * 			java代码:连接对象.rollback();
 * 			DOS窗口:rollback;
 * 3,案例1:使用原生的JDBCAPI完成转账(带有事务和不带事务)
 * 
 * 4.案例2:使用DBUtils工具完成转账(带有事务的和不带事务)
 * 
 * 5.三层思想完成转账:(初级版本BDUtils工具,中级版本加上事务,终极版本编写了ConnectionManager)
 * 
 * 
 * 6.ThreadLocal:线程本地变量
 * 		public class ThreadLocal{
 * 			Map<Thread,Object> map = new Map<Thread,Object>();
 * 			public void set(Object obj){
 * 				map.set(Thread.currentThread(),obj);
 * 			}
 * 			public Object get(){
 * 				map.get(Thread.currentThread());
 * 			}
 * 		}
 *	
 *
 *
 *
 */

 

示例代码:

准备sql语句:

###数据库准备
CREATE DATABASE day06;
###创建账户表 
CREATE TABLE account( aid INT PRIMARY KEY AUTO_INCREMENT , money VARCHAR(100), NAME VARCHAR(100) );

INSERT INTO account (money,NAME) VALUES('999','agen'); 
INSERT INTO account (money,NAME) VALUES('666','nice'); 
INSERT INTO account (money,NAME) VALUES('888','good');

1数据库-在C3P0连接池中+连接管理类

package com.itheima.utils;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
 * 在C3P0连接池中 遵循了javax.sql.DataSource接口的实现类:
 * 		ComboPooledDataSource
 *
 *
 * @author yingpeng
 *
 */
public class C3P0Utils02 {

	private static ComboPooledDataSource ds = new ComboPooledDataSource();


	public static DataSource getDataSource(){
		return ds;
	}
	//static代码块设置数据库连接四大要素

	public static Connection getConnection() throws SQLException{
		//获取连接,不要自己去DriverManager获取,而是从C3P0连接池获取
		return ds.getConnection();
	}

	//关闭所有资源的统一代码
	public static void closeAll(Connection conn,Statement st,ResultSet rs){
		//负责关闭
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(st != null){
			try {
				st.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
package com.itheima.utils;

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

/**
 * 连接管理类:
 * 	主要负责获取连接,开启事务,提交事务,回滚事务
 * @author yingpeng
 *
 */
public class ConnectionManager {
	//1.定义一个集合 ThreadLocal 对象来保存当前线程的连接
	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

	//2.获取连接
	public static Connection getConnection() throws SQLException{
		//1.先从tl中获取连接
		Connection conn =  tl.get();
		//2.判断conn是否为空
		if(conn == null){
			//说明 是service层第一次获取
			conn = C3P0Utils02.getConnection();
			tl.set(conn);
		}
		//如果不为空 说明 是dao层第二次以后获取
		return conn;
	}

	//3.开启事务
	public static  void start() throws SQLException{
		ConnectionManager.getConnection().setAutoCommit(false);
	}

	//4.提交事务
	public static void commit() throws SQLException{
		ConnectionManager.getConnection().commit();
	}
	//5.回滚事务
	public static void rollback() throws SQLException{
		ConnectionManager.getConnection().rollback();
	}
	//6.关闭连接
	public static void close() throws SQLException{
		ConnectionManager.getConnection().close();
	}
}

2dao层-操作数据库

package com.itheima.dao;

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

import org.apache.commons.dbutils.QueryRunner;

import com.itheima.utils.C3P0Utils02;
import com.itheima.utils.ConnectionManager;

/**
 * 转账DAO层,主要就是操作数据库
 *
 * 我们案例中只涉及到修改操作
 *
 * @author yingpeng
 *
 */
public class AccountDao {

	//转账出去
	//jack 转出去 1000元
	public void fromAccount(String fromName,double money) throws SQLException{
		Connection conn = ConnectionManager.getConnection();
		//1.创建QueryRunner对象
		QueryRunner qr = new QueryRunner();
		//2.执行减钱操作
		qr.update(conn,"update account set money=money-? where name=?", money,fromName);
	}

	//收钱回来
	public void toAccount(String toName,double money) throws SQLException{
		Connection conn = ConnectionManager.getConnection();
		//1.创建QueryRunner对象
		QueryRunner qr = new QueryRunner();
		//2.加钱操作
		qr.update(conn,"update account set money=money+? where name=?",money,toName);

	}

}

3service层-转账功能的业务层

package com.itheima.service;

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

import com.itheima.dao.AccountDao;
import com.itheima.utils.C3P0Utils02;
import com.itheima.utils.ConnectionManager;

/**
 * 转账功能的业务层
 *
 * @author yingpeng
 *
 */
public class AccountService {

	//转账业务
	public void transfer(String fromName,String toName,double money){
		//直接调用dao
		AccountDao dao = new AccountDao();
		try {
			//开启事务
			ConnectionManager.start();
			//转出去
			dao.fromAccount(fromName, money);
			//模拟异常
//			System.out.println(1/0);
			//拿回来
			dao.toAccount(toName, money);
			//提交事务
			ConnectionManager.commit();
			System.out.println("转账成功!!!");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("程序出现异常,程序回滚");
			//回滚事务
			try {
				ConnectionManager.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}finally {
			try {
				ConnectionManager.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}


}

4.view层-交互层

package com.itheima.view;

import com.itheima.service.AccountService;

public class AccountView {
	public static void main(String[] args) {
		//模拟用户转账,输入付款人的姓名,收款人的姓名,转账金额
		String fromName = "nice";
		String toName = "agen";
		double money = 5000;

		AccountService service = new AccountService();

		service.transfer(fromName, toName, money);
	}
}

 


版权声明:本文为dianziagen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。