• 利用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
  • 相关阅读:
    3Dtouch 的实际应用详解(tableView中的应用)
    使用UIScrollView的zoomscale实现图片捏合放大
    SVN命令使用详解
    参数传递
    cookie文件路径
    XML和HTML之间的差异
    cssSelector元素定位方法
    如何调用一个数据完整的firefox浏览器
    Android生命周期详解
    android 利用countDownLatch实现主线程与子线程之间的同步
  • 原文地址:https://www.cnblogs.com/friends-wf/p/3749590.html
Copyright © 2020-2023  润新知