利用ThreadLocal建立高质量事务处理
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建立高质量事务处理的更多相关文章
- 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本
建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...
- 编写高质量代码改善C#程序的157个建议——建议55:利用定制特性减少可序列化的字段
建议55:利用定制特性减少可序列化的字段 特性(attribute)可以声明式地为代码中的目标元素添加注释.运行时可以通过查询这些托管块中的元数据信息,达到改变目标元素运行时行为的目的.System. ...
- (转)用AGG实现高质量图形输出(二)
本文上接<用AGG实现高质量图形输出(一)>,分别介绍了AGG显示流程中的各个环节. 上次讲了AGG的显示原理并举了一个简单的例子,这一篇文章开始讲AGG工作流程里的每个环节.为了方便对照 ...
- Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护
Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称password学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文.而解密则是通过解密 ...
- 使用koa2+es6/7打造高质量Restful API
前言 如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用. 在过去,使用nodejs大家首先想到的是TJ大神写的express.js,而发展到如今,更轻量,性能更好 ...
- 编写高质量代码改善C#程序的157个建议——建议117:使用SSL确保通信中的数据安全
建议117:使用SSL确保通信中的数据安全 SSL(Secure Socket Layer)最初是由NetScape公司设计的,用于Web安全的网络协议.目前它已经广泛应用到各类网络传输通信中了.SS ...
- 编写高质量Python程序(四)库
本系列文章为<编写高质量代码--改善Python程序的91个建议>的精华汇总. 按需选择 sort() 或者 sorted() Python 中常用的排序函数有 sort() 和 sort ...
- 怎样编写高质量的java代码
代码质量概述 怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友 ...
- 如何写出高质量的技术博客 这边文章出自http://www.jianshu.com/p/ae9ab21a5730 觉得不错直接拿过来了 好东西要大家分享嘛
如何写出高质量的技术博客?答案是:如果你想,就一定能写出高质量的技术博客.看起来很唯心,但这就是事实.有足够愿力去做一件目标明确,有良好反馈系统的事情往往很简单.就是不停地训练,慢慢地,你自己 ...
随机推荐
- CDOJ 1048 Bob's vector 三分
Bob's vector 题目连接: http://acm.uestc.edu.cn/#/problem/show/1048 Description Bob has a vector with mm ...
- IntelliJ IDEA导出设置
导出: [File]->[Export Settings] 导入: [File]->[Import Settings]
- Tasker 正则表达式测试器
http://tieba.baidu.com/p/3533498043 本次分享的是一个正则表达式测试工具,用来方便快捷的进行Tasker正则方面的测试,一些比较复杂的匹配需要进行多次尝试才可能正确匹 ...
- Add margining capability to a dc/dc converter
You can easily add margining capability—that is, the ability to digitally adjust the output voltage— ...
- spring学习之@ModelAttribute运用详解
@ModelAttribute使用详解 1.@ModelAttribute注释方法 例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方法 ...
- MySQL 一个库中表数量是否有限制?
在网上找了一下,有说几乎没有限制的,也有说表多了肯定会影响性能的,综合起来应该讲: 1)一个库中表数是有限制的, 按照 UNSIGNED 类型,最多42亿多一点,正常应用根本达不到. 2)文件系统 ...
- Apache下error.log文件太大的处理
偶尔发现Apache下的错误日志非常的大,有4G多,先停止Apache服务的所有进程,最简单就是输命令:net stop apache2.2,然后删除 Apache2/logs/目录下的 error. ...
- python接口自动化8-参数化
前言 前面一篇实现了参数的关联,那种只是记流水账的完成功能,不便于维护,也没什么可读性,接下来这篇可以把每一个动作写成一个函数,这样更方便了. 参数化的思维只需记住一点:不要写死 (由于博客园登录机制 ...
- Mantis使用说明
Mantis是一个缺陷跟踪系统,以Web操作的形式提供项目管理及缺陷跟踪服务. Mantis可以帮助所有开发人员完成系统需求缺陷的有效管理,对于bug问题的状态变化将通过mail的形式由系统自动通知相 ...
- webbrowser 常用方法(C#)
0.常用方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(st ...