首页 > 代码库 > 利用ThreadLocal建立高质量事务处理

利用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   )
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

测试

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