JDBC事务(三)ThreadLocal绑定Connection
处理一个请求即开启一个线程,在三层中,执行三层中的方法都是用的同一个线程。
我们开启一个事务,使用conn.setAutoCommit(false); conn应该属于ado层,不应该出现在service层,但处理事务应该在service层执行。
针对上述矛盾,我们考虑将Connection绑定到ThreadLocal中,因为三层的执行都是在同一个线程,当需要Connection时,从ThreadLocal中取即可。
更改上一章转账按例,结构如下:

更改C3P0线程池的工具类 MyDataSourceUtils
package cn.sasa.util; import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class MyDataSourceUtils {
private static DataSource dataSource = new ComboPooledDataSource("mydb"); public static DataSource getDataSource() {
return dataSource;
} public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
} //当前线程
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>(); // 获得当前线程上绑定的conn
public static Connection getCurrentConnection() throws SQLException {
// 从ThreadLocal找 当前线程是否有对应的Connection
Connection conn = threadLocal.get();
if (conn == null) {
conn = getConnection();
// 将conn绑定到ThreadLocal(map)上
threadLocal.set(conn);
}
return conn;
} // 开启事务
public static void StartTransaction() throws SQLException {
Connection conn = getCurrentConnection();
conn.setAutoCommit(false);
} // 回滚事务
public static void rollback() throws SQLException {
Connection conn = getCurrentConnection();
conn.rollback();
threadLocal.remove();
conn.close();
} // 提交事务
public static void commit() throws SQLException {
Connection conn = getCurrentConnection();
conn.commit();
threadLocal.remove();
conn.close();
}
}
更改service层代码:
package cn.sasa.service; import java.sql.SQLException; import cn.sasa.dao.TransferDao;
import cn.sasa.util.MyDataSourceUtils; public class TransferService { public boolean doTran(String outAccount, String inAccount, double money) {
boolean flag = true; try {
MyDataSourceUtils.StartTransaction(); TransferDao tran = new TransferDao();
int rs1 = tran.doOutAccount(outAccount, money);
int rs2 = tran.doInAccount(inAccount, money); if(rs1<=0 || rs2<=0) {
MyDataSourceUtils.rollback();
flag=false;
} } catch (Exception e) {
flag = false;
try {
MyDataSourceUtils.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
MyDataSourceUtils.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
return flag;
}
}
更改dao层:
package cn.sasa.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import cn.sasa.util.MyDataSourceUtils;
public class TransferDao {
//资金转出
public int doOutAccount( String outAccount, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "update account set money=money-? where name=?";
int rs = runner.update(MyDataSourceUtils.getCurrentConnection(), sql, money,outAccount);
return rs;
}
//资金转入
public int doInAccount(String inAccount, double money) throws SQLException {
QueryRunner runner = new QueryRunner();
String sql = "update account set money=money+? where name=?";
int rs = runner.update(MyDataSourceUtils.getCurrentConnection(), sql, money,inAccount);
return rs;
}
}
web层与客户端jsp页面略。
客户端请求一次即开启一个线程,再次请求则开启另一个线程。
JDBC事务(三)ThreadLocal绑定Connection的更多相关文章
- 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别
1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...
- JDBC事务--软件开发三层架构--ThreadLocal
JDBC事务--软件开发三层架构--ThreadLocal 一.JDBC事务 1.概述: 事务是指逻辑上的一组操作!这一组操作,通常认为是一个整体,不可拆分! 特点:同生共死;事务内的这一组操作要么全 ...
- JDBC(三)----JDBC控制事务
## JDBC控制事务 1.事务:一个包含多个步骤的业务操作.如果这个业务员操作被事务管理,则这多个步骤要么同时成功,要么同时失败. 2.操作: 1.开启事务 2.提交事务 3.回滚事务 3.使用C ...
- Mysql事务与JDBC事务管理
一.事务概述 1.什么是事务 一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败 就是将n个组成单元放到一个事务中 2.mysql的事务 默认的事务:一条sql语句就是一个事务 ...
- JDBC 事务控制
一.简介: 前面一遍提到了jdbc事务相关的概念.从中了解到事务应具有ACID特性.所以对于javaweb开发来说,某一个service层的方法,应该是一个事务,应该是具有原子性的.特别是当一个ser ...
- Java的JDBC事务详解(转)
事务的特性: 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行. 2) 一致性(consistency):事务在完 ...
- Java的JDBC事务详解
Java的JDBC事务详解 分类: Hibernate 2010-06-02 10:04 12298人阅读 评论(9) ...
- day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)
day18总结 今日思维导图: 今日内容 事务 连接池 ThreadLocal BaseServlet自定义Servlet父类(只要求会用,不要求会写) DBUtils à commons-dbuti ...
- 分层架构下的纯JDBC事务控制简单解决方案【转】
http://blog.csdn.net/qjyong/article/details/5464835 对目前的JavaEE企业应用开发来说,基本都会采用分层的架构, 这样可以分散关注.松散耦合.逻辑 ...
随机推荐
- iOS12
ios 12 中的新特性. 已经有很多文章写得很好,这里不再赘述,直接给大家几个传送门: https://sspai.com/post/47168 https://post.smzdm.com/p/7 ...
- 【解惑】领略Java内部类的“内部”
转自:http://www.iteye.com/topic/494230 内部类有两种情况: (1) 在类中定义一个类(私有内部类,静态内部类) (2) 在方法中定义一个类(局部内部类,匿名内部类) ...
- C# 托管内存与非托管内存之间的转换
c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...
- CPU与GPU性能的比较报告
运行时间分析 不同的模型在cpu和gpu下的时间差异较大,一般来说gpu会比cpu快5-20倍.我们选用了最常用的inception v3的分类模型,输入图片尺寸为:3x299x299. GPU 在一 ...
- python 读取大文件,按照字节读取
def read_bigFile(): f = open("123.dat",'r') cont = f.read() : print(cont) cont = f.read() ...
- mac os下不同工具go env下gopath显示不同
设置 vim ~/.zshrc 设置 vim ~/.bash_profile
- 使用 Postman 取得 Token 打另一隻 API
使用 Postman 取得 Token 打另一隻 API Spring MVC token 统一校验和user 信息自动获取 使用token和SpringMVC来实现安全的RESTFul接口 spri ...
- Linux 特殊字符_008
Linux 特殊字符用于用户命令行bash环境处理数据,达到一种命令简化使用的功能 通配符 符号 功能 备注 * 代表所有(0到多个)字符 ? 代表任意一个字符 [ ] 匹配[ ]任意一个字符,写法[ ...
- Houdini技术体系 基础管线(四) :Houdini驱动的UE4植被系统 上篇
背景 之前在<Houdini技术体系 过程化地形系统(一):Far Cry5的植被系统分析>一文中已经对AAA游戏中过程化植被的需求有了一定的定义,后续工作就是如何用Houdini开发功能 ...
- Redis 数据结构的实现
Redis 数据结构的实现 先看个对照关系: Redis数据结构 实现一 实现二 string 整数(如果value能够表示为整数) 字符串 hash 压缩列表(只包含少量键值对, 并且每个键值对的键 ...