处理一个请求即开启一个线程,在三层中,执行三层中的方法都是用的同一个线程。

我们开启一个事务,使用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的更多相关文章

  1. 网络协议 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 ...

  2. JDBC事务--软件开发三层架构--ThreadLocal

    JDBC事务--软件开发三层架构--ThreadLocal 一.JDBC事务 1.概述: 事务是指逻辑上的一组操作!这一组操作,通常认为是一个整体,不可拆分! 特点:同生共死;事务内的这一组操作要么全 ...

  3. JDBC(三)----JDBC控制事务

    ##  JDBC控制事务 1.事务:一个包含多个步骤的业务操作.如果这个业务员操作被事务管理,则这多个步骤要么同时成功,要么同时失败. 2.操作: 1.开启事务 2.提交事务 3.回滚事务 3.使用C ...

  4. Mysql事务与JDBC事务管理

    一.事务概述 1.什么是事务 一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败 就是将n个组成单元放到一个事务中 2.mysql的事务 默认的事务:一条sql语句就是一个事务 ...

  5. JDBC 事务控制

    一.简介: 前面一遍提到了jdbc事务相关的概念.从中了解到事务应具有ACID特性.所以对于javaweb开发来说,某一个service层的方法,应该是一个事务,应该是具有原子性的.特别是当一个ser ...

  6. Java的JDBC事务详解(转)

    事务的特性: 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行. 2) 一致性(consistency):事务在完 ...

  7. Java的JDBC事务详解

    Java的JDBC事务详解         分类:             Hibernate              2010-06-02 10:04     12298人阅读     评论(9) ...

  8. day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)

    day18总结 今日思维导图: 今日内容 事务 连接池 ThreadLocal BaseServlet自定义Servlet父类(只要求会用,不要求会写) DBUtils à commons-dbuti ...

  9. 分层架构下的纯JDBC事务控制简单解决方案【转】

    http://blog.csdn.net/qjyong/article/details/5464835 对目前的JavaEE企业应用开发来说,基本都会采用分层的架构, 这样可以分散关注.松散耦合.逻辑 ...

随机推荐

  1. 【C++】C++中assert和ENDEGU预处理语句

    assert 断言语句是C++中的一种预处理宏语句,它能在程序运行时根据否定条件中断程序. C++中的assert()函数可以实现断言功能,在使用assert函数之前应该先引入<cassert& ...

  2. zabbix之微信告警(python版):微信个人报警,微信企业号告警脚本

    微信个人告警脚本 微信个人告警:使用个人微信,发送到微信群组,微信好友 两个脚本执行: 1)能连接网络2)先执行server.py,扫描登录微信,登录之后没有报错,打开新终端查看端口是否起来了3)在z ...

  3. 使用GoAccess构建简单实时日志分析系统

    很早就知道Nginx日志分析工具GoAccess,但之前由于只能静态分析,感觉不太强大.最近发现它能够实时显示报表而且报表也比之前强大很多能做趋势分析.因此果断下载安装.以下是基于CentOS的安装配 ...

  4. 12款 JavaScript 表格控件(DataGrid)

    JavaScript 表格控件可以操作大数据集的 HTML表格,提供各种功能,如分页.排序.过滤以及行编辑.在本文中,我们整理了13个最好的 JavaScript 表格插件分享给开发人员,开发者可以很 ...

  5. React Native常用组件之ListView

    1. ListView常用属性 ScrollView 相关属性样式全部继承 dataSource ListViewDataSource 设置ListView的数据源 initialListSize n ...

  6. WOW.js和animate.css让页面滚动时显示动画

    官网:http://mynameismatthieu.com/WOW/ bootstrap CDN服务:http://www.bootcdn.cn/wow/ 1.wow.js 实现了在网页滚动时的动画 ...

  7. oozie调度sqoop Job 数据库密码无法保存

    问题描述 通过oozie调度sqoop作业时,需要输入数据库作业密码,但在sqoop元数据服务配置密码后,过一段时间会失效. 解决方法 将数据库密码写入HDFS文件,通过配置Sqoop job,实现传 ...

  8. JavaScript系统对象

    1. 本地对象(非静态对象) 常用对象有: Object.Function.Array.String.Boolean.Number.Date.RegExp.Error 注:本地对象需要new之后再使用 ...

  9. 【MyBatis学习06】_parameter:解决There is no getter for property named in class java.lang.String

    我们知道在mybatis的映射中传参数,只能传入一个.通过#{参数名} 即可获取传入的值. Mapper接口文件: public int delete(int id) throws Exception ...

  10. A real example of vioplot in R (sample data and code attached)

    Basic information Package name: vioplot Package homepage: https://cran.r-project.org/web/packages/vi ...