利用ThreadLocal建立高质量事务处理

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

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

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

数据库表


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

domain中


 1 package cn.itcast.domain;
2
3 import java.io.Serializable;
4
5 public class Account implements Serializable {
6
7 private int id;
8 private String name;
9 private float money;
10 public Account() {
11 }
12 public int getId() {
13 return id;
14 }
15 public void setId(int id) {
16 this.id = id;
17 }
18 public String getName() {
19 return name;
20 }
21 public void setName(String name) {
22 this.name = name;
23 }
24 public float getMoney() {
25 return money;
26 }
27 public void setMoney(float money) {
28 this.money = money;
29 }
30 @Override
31 public String toString() {
32 return "Account [id=" + id + ", name=" + name + ", money=" + money
33 + "]";
34 }
35
36 }

utils中TransactionUtil.java


  1 package cn.itcast.utils;
2
3 import java.io.InputStream;
4 import java.sql.Connection;
5 import java.sql.SQLException;
6 import java.util.Properties;
7
8 import javax.sql.DataSource;
9
10 import org.apache.commons.dbcp.BasicDataSourceFactory;
11
12 public class TransactionUtil {
13 private static ThreadLocal<Connection> t=new ThreadLocal<Connection>();
14
15 private static DataSource ds;
16 static{
17 try {
18 InputStream in = TransactionUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
19 Properties props = new Properties();
20 props.load(in);
21 ds = BasicDataSourceFactory.createDataSource(props);
22 } catch (Exception e) {
23 e.printStackTrace();
24 }
25 }
26
27 public static DataSource getDataSource(){
28 return ds;
29 }
30
31 public static Connection getConnection()
32 {
33 Connection con=null;
34 try {
35 con = t.get();// 获取 value,为 Connection对象 用于事务的处理
36 if(con==null)
37 {
38 con=ds.getConnection();
39 t.set(con);
40 }
41 } catch (SQLException e) {
42 e.printStackTrace();
43 }
44 return con;
45 }
46 public static void startTransaction() throws SQLException //把异常抛出去 ,让后面调用 事务 获取异常然后rollback
47 {
48 Connection con=null;
49 try {
50 con = t.get(); //如果前面调用过getConnection(),则con!=null,以下相同
51 if(con==null)
52 {
53 t.set(ds.getConnection());
54 }
55 con.setAutoCommit(false); //开启事务
56 } catch (SQLException e) {
57 e.printStackTrace();
58 throw e;
59 }
60 }
61 public static void commitTransaction() throws SQLException
62 {
63 Connection con=null;
64 try {
65 con = t.get();
66 if(con==null)
67 {
68 t.set(ds.getConnection());
69 }
70 con.commit();
71 } catch (SQLException e) {
72 e.printStackTrace();
73 throw e;
74 }
75 }
76 public static void rollbackTransaction() throws SQLException
77 {
78 Connection con=null;
79 try {
80 con = t.get();
81 if(con==null)
82 {
83 t.set(ds.getConnection());
84 }
85 con.rollback();
86 } catch (SQLException e) {
87 e.printStackTrace();
88 throw e;
89 }
90 }
91 public static void release()
92 {
93 Connection con=null;
94
95 try {
96 con = t.get();
97 if(con!=null)
98 {
99 con.close();
100 t.remove();
101 }
102 } catch (SQLException e) {
103 e.printStackTrace();
104 }
105
106 }
107
108 }

daoImpl中


 1 package cn.itcast.dao.impl;
2
3 import java.sql.SQLException;
4
5 import org.apache.commons.dbutils.QueryRunner;
6 import org.apache.commons.dbutils.handlers.BeanHandler;
7
8 import cn.itcast.domain.Account;
9 import cn.itcast.utils.TransactionUtil;
10
11 public class AccountDaoImpl {
12 private QueryRunner qr = new QueryRunner();
13 public void updateAccount(Account c)
14 {
15 try {
16 String sql="update account_table set money=? where name=?";
17 qr.update(TransactionUtil.getConnection(),sql,c.getMoney(),c.getName());
18 } catch (SQLException e) {
19 e.printStackTrace();
20 }
21 }
22
23 public Account findAccount(String accountName)
24 {
25 try {
26 String sql="select * from account_table where name=?";
27 return qr.query(TransactionUtil.getConnection(),sql, new BeanHandler<Account>(Account.class),accountName);
28 } catch (SQLException e) {
29 e.printStackTrace();
30 }
31 return null;
32 }
33 }

serviceImpl中


 1 package cn.itcast.ServiceImpl;
2
3 import java.sql.SQLException;
4
5 import cn.itcast.dao.impl.AccountDaoImpl;
6 import cn.itcast.domain.Account;
7 import cn.itcast.utils.TransactionUtil;
8
9 public class AccountServeImpl {
10 public AccountDaoImpl dao=new AccountDaoImpl();
11 public void transe(String name1,String name2,int money)
12 {
13 Account c1=dao.findAccount(name1);
14 Account c2=dao.findAccount(name2);
15
16
17 c1.setMoney(c1.getMoney()-money);
18 c2.setMoney(c2.getMoney()+money);
19
20 try {
21 TransactionUtil.startTransaction();
22 dao.updateAccount(c1);
23 int i=1/0; //发现异常
24 dao.updateAccount(c2);
25 } catch (Exception e) { //一定要用 捕获的异常来捕获
26 try {
27 TransactionUtil.rollbackTransaction();
28 } catch (SQLException e1) {
29 e1.printStackTrace();
30 }
31 e.printStackTrace();
32 }
33 finally
34 {
35 try {
36 TransactionUtil.commitTransaction();
37 TransactionUtil.release();
38 } catch (SQLException e) {
39 e.printStackTrace();
40 }
41 }
42
43 }
44 }

测试


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

利用ThreadLocal建立高质量事务处理

时间: 2024-09-28 07:35:27

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

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

建议55:利用定制特性减少可序列化的字段 特性(attribute)可以声明式地为代码中的目标元素添加注释.运行时可以通过查询这些托管块中的元数据信息,达到改变目标元素运行时行为的目的.System.Runtime.Serialization命名空间下,有4个这样的特性: OnDeserializedAttribute,当它应用于某方法时,会指定在对象反序列化后立即调用此方法. OnDeserializingAttribute,当他应用于某方法是,会指定在反序列化对象时调用此方法. OnSeri

利用这四大技巧 轻松打造高质量的网站内容

在制作网站的过程中,怎样为企业网站打造一些高质量的网站内容呢?因为高质量的内容可以提高网站的表现效果,而且可以吸引更多的流量,提升网站的权重.今天我们就来说一下网站制作过程中,怎样打造优质的内容.下面我们就一起来聊一下吧. 第一.为网站选择一个易记简短的域名.一个稳定的网站服务空间.易记简短的域名不仅方便用户可以很容易快速地记住你的网站.从搜索引擎收录网站的角度来看,对简单的域名也是比较感兴趣的.因此,很多企业网站在制作的时候一般都会选择com域名注册.而作为一个营销类型的网站,而且是想要打开网

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

Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称密码学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文.数据加密目前仍是计算机系统对信息进行保护的一种最可靠的办法.它利用密码技术对信息进行加密,实现信息隐蔽,从而起到保护信息的安全的作用. 一.概述 数据加密是指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文.它产生的历史相当久远,它是起源于

如何构建高质量的代码?

一.高质量代码的三要素 可读性.可维护性.可变更性(所有软件理论的核心) 1.可读性强 1.1.why 程序员写不出可读性的代码? 原因有三: 他们很少关注代码的可读性,也对如何提高代码的可读性缺乏切身体会. 有时即使为代码编写了注释,也常常是注释语言晦涩难懂形同天书,令阅读者反复斟酌依然不明其意. 项目开发的时间往往是有限.紧急的.(可使用eclipse中的代码模板) 1.2.建议 1)不要编写大段的代码: 在编码过程中,不断地对代码进行分段.分离,写成一个个函数,并要考虑这些函数应该放在哪里

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

本文上接<用AGG实现高质量图形输出(一)>,分别介绍了AGG显示流程中的各个环节. 上次讲了AGG的显示原理并举了一个简单的例子,这一篇文章开始讲AGG工作流程里的每个环节.为了方便对照,再放一次AGG显示流程 图 另外,上一篇文章里的例程也很重要,后面的例子都将基于这个代码. 下面,我们来考察AGG显示流程中的每个环节.理解每个环节最好的方法是编写实验代码,建议先参照这里建 立一个可以运行的AGG实验环境. 顶点源(Vertex Source) 顶点源是一种可以产生多边形所需要的“带命令的

高质量代码三要素:可读性、可维护性、可变更性(转)

今天这堂培训课讲什么呢?我既不讲Spring,也不讲Hibernate,更不讲Ext,我不讲任何一个具体的技术.我们抛开任何具体的技术,来谈谈如何提高代码质量.如何提高代码质量,相信不仅是在座所有人苦恼的事情,也是所有软件项目苦恼的事情.如何提高代码质量呢,我认为我们首先要理解什么是高质量的代码. 高质量代码的三要素 我们评价高质量代码有三要素:可读性.可维护性.可变更性.我们的代码要一个都不能少地达到了这三要素的要求才能算高质量的代码. 1. 可读性强 一提到可读性似乎有一些老生常谈的味道,但

如何开发高质量的软件 - 通过测试集中型的软件开发方法来提高软件质量

“构建技术系统所要做的工作是非常繁重的,同时还需要专业知识:语言和协议,编码与调试,测试与重构.”——James Garrett 概述 每年各个企业都在努力实现企业的主要目标.通常,这都是通过实现基于度量指标的性能目标(可能包括质量目标)以及利用最佳惯例规范商业流程来实现的.最 后,要通过一些测试和报告形式来评估这些目标对企业的影响.在接受评估之前,机智的员工都会要一个评估单——但是在开发新的软件产品,确定测试目标时,他 们常常会忽略这一点. 企业在设计实体产品时,会花很多时间设计产品的生成流程

[译]Quora是如何维持高质量代码的

原文链接:Moving Fast With High Code Quality译者:杰微刊—程慧 一个高质量的代码库可以加快长期开发的速度,因为它会使得迭代.协作和维护更加容易.在Quora,我们十分重视代码库的质量. 除了会取得收益之外,要维护高质量的代码,会带来一大笔间接费用,还会牺牲实际开发周期.很多人发现,实际产生的收益很难抵消这一间接费用,这时人们会面临两个选择:要么以低质量代码提升开发速度,要么维护高质量代码而牺牲开发速度.而对于初创公司来说,他们希望开发速度能快一些,所以就不得不使

怎么才能制造出高质量的led透镜

质量决议销量,为了能让销量不断的添加,质量是第一位的.对于以出售led透镜公司而言,出产高质量的透镜才干有更大的销量,才干取得十分好的商场以及更大的赢利.出产高质量的led透镜的办法成为每个出产公司必备的原则. 出产led透镜需求遵循什么样的请求,才会契合消费者要,运用作用佳?首先取决于光源,大功率LED,不一样品牌的大功率LED,其芯片构造与封装方法.光线特性等均会有所区别,然后形成同样的透镜搭配不一样标准品牌LED时会所区别:所以请求有针对性开发,才干达到实践需求.其非必须利用光学规划软件,