【Java基础】采用ThreadLocal封装Connection控制事务,保证线程安全

来源:互联网 发布:数据连接老是自动打开 编辑:程序博客网 时间:2024/06/04 17:49

前言:

上篇博客介绍了ThreadLocal的原理和功能,这篇博客会做一个ThreadLocal的具体示例:采用ThreadLocal封装Connection,控制事务,保证线程安全。

原理:

采用ThreadLocal封装Connection后,每个线程使用connection时,都会创建一份connection,但是每个线程里的方法全部使用自己创建的那份connection,相互线程间不受影响。从而达到控制事务的目的。

ConnectionManager封装事务和Connection

package com.bjpowernode.drp.util;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/** * 采用ThreadLocal封装Connection * 添加事务控制方法 * @author Administrator * */public class ConnectionManager {    private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();    /**     * 得到Connection     * @return     */    public static Connection getConnection() {        Connection conn = connectionHolder.get();        //如果在当前线程中没有绑定相应的Connection        if (conn == null) {            try {                JdbcConfig jdbcConfig = XmlConfigReader.getInstance().getJdbcConfig();                Class.forName(jdbcConfig.getDriverName());                conn = DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUserName(), jdbcConfig.getPassword());                //将Connection设置到ThreadLocal                connectionHolder.set(conn);            } catch (ClassNotFoundException e) {                e.printStackTrace();                throw new ApplicationException("系统错误,请联系系统管理员");            } catch (SQLException e) {                e.printStackTrace();                throw new ApplicationException("系统错误,请联系系统管理员");            }        }        return conn;    }    public static void closeConnection() {        Connection conn = connectionHolder.get();        if (conn != null) {            try {                conn.close();                //从ThreadLocal中清除Connection                connectionHolder.remove();            } catch (SQLException e) {                e.printStackTrace();            }           }    }    public static void close(Connection conn) {        if (conn != null) {            try {                conn.close();            } catch (SQLException e) {                e.printStackTrace();            }        }    }    public static void close(Statement pstmt) {        if (pstmt != null) {            try {                pstmt.close();            } catch (SQLException e) {                e.printStackTrace();            }        }    }    public static void close(ResultSet rs ) {        if (rs != null) {            try {                rs.close();            } catch (SQLException e) {                e.printStackTrace();            }        }    }    public static void beginTransaction(Connection conn) {        try {            if (conn != null) {                if (conn.getAutoCommit()) {                    conn.setAutoCommit(false); //手动提交                }            }        }catch(SQLException e) {}    }    public static void commitTransaction(Connection conn) {        try {            if (conn != null) {                if (!conn.getAutoCommit()) {                    conn.commit();                }            }        }catch(SQLException e) {}    }    public static void rollbackTransaction(Connection conn) {        try {            if (conn != null) {                if (!conn.getAutoCommit()) {                    conn.rollback();                }            }        }catch(SQLException e) {}    }}


manager层调用示例:

public void addFlowCard(FlowCard flowCard) throws ApplicationException {        Connection conn = null;        try {            //取得Connection            conn = ConnectionManager.getConnection();            //开始事务            ConnectionManager.beginTransaction(conn);            //生成流向单单号            String flowCardVouNo = flowCardDao.generateVouNo();            //添加流向单主信息            flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);            //添加流向单明细信息            flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());            //提交事务            ConnectionManager.commitTransaction(conn);        }catch(DaoException e) {            //回滚事务            ConnectionManager.rollbackTransaction(conn);            throw new ApplicationException("添加流向单失败!");        }finally {            //关闭Connection并从ThreadLocal中清除            ConnectionManager.closeConnection();        }    }



采用ThreadLocal封装Connection后,可以保证线程安全,因为他隔离的相关的资源,使得相互线程间不受影响,并可以在同一个线程中共享这个资源,他只是保证线程安全的一种手段,同样我们也可以通过同步机制来解决线程安全问题。

0 0
原创粉丝点击