代码仓库+教程文档: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版权协议,转载请附上原文出处链接和本声明。