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

前言:

上篇博客介绍了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后,可以保证线程安全,因为他隔离的相关的资源,使得相互线程间不受影响,并可以在同一个线程中共享这个资源,他只是保证线程安全的一种手段,同样我们也可以通过同步机制来解决线程安全问题。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值