ThreadLocal此类是一个以当前线程为key的map对象的构想。

当我们在web开发中,多个浏览器访问的时候,servlet为它们各开线程执行相应代码,而事务的执行依赖于特定的一个Connection对象当中。所以用到了ThreadLocal类来封装<Connection>来取和放。

业务逻辑中不出现 Connection对象,代码风格好

数据库表

 create table account
( id int primary key,
name varchar(20),
float money(8,2)
)

domain中

 package cn.itcast.domain;

 import java.io.Serializable;

 public class Account implements Serializable {

     private int id;
private String name;
private float money;
public Account() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getMoney() {
return money;
}
public void setMoney(float money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money
+ "]";
} }

utils中TransactionUtil.java

 package cn.itcast.utils;

 import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class TransactionUtil {
private static ThreadLocal<Connection> t=new ThreadLocal<Connection>(); private static DataSource ds;
static{
try {
InputStream in = TransactionUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties props = new Properties();
props.load(in);
ds = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
} public static DataSource getDataSource(){
return ds;
} public static Connection getConnection()
{
Connection con=null;
try {
con = t.get();// 获取 value,为 Connection对象 用于事务的处理
if(con==null)
{
con=ds.getConnection();
t.set(con);
}
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
public static void startTransaction() throws SQLException //把异常抛出去 ,让后面调用 事务 获取异常然后rollback
{
Connection con=null;
try {
con = t.get(); //如果前面调用过getConnection(),则con!=null,以下相同
if(con==null)
{
t.set(ds.getConnection());
}
con.setAutoCommit(false); //开启事务
} catch (SQLException e) {
e.printStackTrace();
throw e;
}
}
public static void commitTransaction() throws SQLException
{
Connection con=null;
try {
con = t.get();
if(con==null)
{
t.set(ds.getConnection());
}
con.commit();
} catch (SQLException e) {
e.printStackTrace();
throw e;
}
}
public static void rollbackTransaction() throws SQLException
{
Connection con=null;
try {
con = t.get();
if(con==null)
{
t.set(ds.getConnection());
}
con.rollback();
} catch (SQLException e) {
e.printStackTrace();
throw e;
}
}
public static void release()
{
Connection con=null; try {
con = t.get();
if(con!=null)
{
con.close();
t.remove();
}
} catch (SQLException e) {
e.printStackTrace();
} } }

daoImpl中

 package cn.itcast.dao.impl;

 import java.sql.SQLException;

 import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import cn.itcast.domain.Account;
import cn.itcast.utils.TransactionUtil; public class AccountDaoImpl {
private QueryRunner qr = new QueryRunner();
public void updateAccount(Account c)
{
try {
String sql="update account_table set money=? where name=?";
qr.update(TransactionUtil.getConnection(),sql,c.getMoney(),c.getName());
} catch (SQLException e) {
e.printStackTrace();
}
} public Account findAccount(String accountName)
{
try {
String sql="select * from account_table where name=?";
return qr.query(TransactionUtil.getConnection(),sql, new BeanHandler<Account>(Account.class),accountName);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}

serviceImpl中

 package cn.itcast.ServiceImpl;

 import java.sql.SQLException;

 import cn.itcast.dao.impl.AccountDaoImpl;
import cn.itcast.domain.Account;
import cn.itcast.utils.TransactionUtil; public class AccountServeImpl {
public AccountDaoImpl dao=new AccountDaoImpl();
public void transe(String name1,String name2,int money)
{
Account c1=dao.findAccount(name1);
Account c2=dao.findAccount(name2); c1.setMoney(c1.getMoney()-money);
c2.setMoney(c2.getMoney()+money); try {
TransactionUtil.startTransaction();
dao.updateAccount(c1);
int i=1/0; //发现异常
dao.updateAccount(c2);
} catch (Exception e) { //一定要用 捕获的异常来捕获
try {
TransactionUtil.rollbackTransaction();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
finally
{
try {
TransactionUtil.commitTransaction();
TransactionUtil.release();
} catch (SQLException e) {
e.printStackTrace();
}
} }
}

测试

     @Test
public void test() {
AccountServeImpl service=new AccountServeImpl();
service.transe("chenlongfei", "wangfang", 100);
}

利用ThreadLocal建立高质量事务处理的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  2. 编写高质量代码改善C#程序的157个建议——建议55:利用定制特性减少可序列化的字段

    建议55:利用定制特性减少可序列化的字段 特性(attribute)可以声明式地为代码中的目标元素添加注释.运行时可以通过查询这些托管块中的元数据信息,达到改变目标元素运行时行为的目的.System. ...

  3. (转)用AGG实现高质量图形输出(二)

    本文上接<用AGG实现高质量图形输出(一)>,分别介绍了AGG显示流程中的各个环节. 上次讲了AGG的显示原理并举了一个简单的例子,这一篇文章开始讲AGG工作流程里的每个环节.为了方便对照 ...

  4. Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护

    Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称password学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文.而解密则是通过解密 ...

  5. 使用koa2+es6/7打造高质量Restful API

    前言 如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用. 在过去,使用nodejs大家首先想到的是TJ大神写的express.js,而发展到如今,更轻量,性能更好 ...

  6. 编写高质量代码改善C#程序的157个建议——建议117:使用SSL确保通信中的数据安全

    建议117:使用SSL确保通信中的数据安全 SSL(Secure Socket Layer)最初是由NetScape公司设计的,用于Web安全的网络协议.目前它已经广泛应用到各类网络传输通信中了.SS ...

  7. 编写高质量Python程序(四)库

    本系列文章为<编写高质量代码--改善Python程序的91个建议>的精华汇总. 按需选择 sort() 或者 sorted() Python 中常用的排序函数有 sort() 和 sort ...

  8. 怎样编写高质量的java代码

    代码质量概述     怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友 ...

  9. 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛

        如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...

随机推荐

  1. 如果内容很长ueditor编辑辑器怎么出现滚动条

    在开发网站的时候,有的页面需要加载ueditor编辑器,如果内容很长,默认设置的时候编辑器会根据内容拉长,而不是页面出现滚动条,如果拖动页面滚条,会比较麻烦,要拖动很长才能看到提交按钮. 如何才能让编 ...

  2. Use an LM317 as 0 to 3V adjustable regulator

    Most engineers know that they can use an inexpensive, three-terminal adjustable regulator, such as F ...

  3. Spring MVC概述

    Spring MVC框架是一个开源的Java平台,为开发强大的基于Java的Web应用程序提供全面的基础架构支持非常容易和非常快速. Spring框架最初由Rod Johnson撰写,并于2003年6 ...

  4. Unity3D如何减少安装包大小

    译官方文档:http://docs.unity3d.com/Manual/ReducingFilesize.html PDF文档:http://www.rukawa.cn/Uploads/Attach ...

  5. Unity的shader学习2

    下面继续看基于surface的shader代码,基本与Vertex&Fragment shader差不多,只是不能写pass,然后只需要声明surface函数,就能处理所有的事情. Shade ...

  6. C#中使用SQLite数据库简介(下)

    [SQLite管理工具简介] 推荐以下2款: Navicat for SQLite:功能非常强大,几乎包含了数据库管理工具的所有必需功能,操作简单,容易上手.唯一的缺点是不能打开由System.Dat ...

  7. Quartz学习笔记

    :30发送email通知客户最新的业务情况. java.util.Timer和java.util.TimerTask    Timer和TimerTask是能够完毕job schedule的两个jdk ...

  8. Android -- ListView与Adapter

    ListView在Android中有着很重要的作用.Android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示. 背景              ...

  9. jquery ajax方式直接提交整个表单

    $.ajax({ type: "POST", url: url, data: $('#form1').serialize(), success: function(msg){ al ...

  10. Cognos清除本地高速缓存的利与弊

    场景:在开发报表初期,往往我们遇到过这种问题,我们手工修改了DB中的测试数据,但是返回报表看,数据还没有更新,难道是设计出问题了?NO,不要慌,这是因为Cognos为了查询效率设计了高速缓存的选项. ...