首页 > 代码库 > 采用ThreadLocal维护Connection

采用ThreadLocal维护Connection

        在以前的项目中,也曾经使用过事务的机制,总结说来一共有三种(其实本质都是一样的,只是表现形式不同):

        第一种:在数据库中直接写在存储过程中(这个最简单,这里不再说明,存在的问题是代码完全不能复用,那里使用要单独写sql语句)

        第二种:采用分层的思想进行设计,在D层进行方法的封装(这个很像直接写在数据库中存在的问题和上面的也一样——复用问题)。

        第三种:在D层只写细粒度的操作方法,在上一层或者其他层开启事务进行组装,这种方法往往涉及到Connection的传递问题,当然在我原来的博客中也有写放在静态变量中D层用的时候直接取得。当然这样做是没有考虑线程安全的问题的。如果进行传递也是一件很麻烦的事。

        我们采用ThreadLocal维护Connection可以避免这种情况。

        ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。

        该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。

     ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联,即在同一个线程,可以共享该资源。

        采用ThreadLocal维护Connection实例

package com.hanyi.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 hanyi
 *
 */
public class ConnectionManage {
	//用于保存connection
	private static ThreadLocal<Connection> connectionHolder=new ThreadLocal<Connection>();

	/**
	 * 获取连接
	 * @return
	 */
	public static Connection GetConnection()
	{
		Connection conn=connectionHolder.get();
		
		
		if(conn==null)
		{
			try {
				JdbcConfig jdbcConfig=XmlConfigReader.GetInstance().getJdbcConfig();
				Class.forName(jdbcConfig.getDriverName());
				conn=DriverManager.getConnection(jdbcConfig.getUrl(),jdbcConfig.getUserName(),jdbcConfig.getPassword());
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			connectionHolder.set(conn);
		}
		
		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();
			}	
		}
	}
	
	//关闭Statement(用于执行静态 SQL 语句并返回它所生成结果的对象。)
	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) {}
	}
}

        这样操作完全解决了一起的问题:1.细粒度代码的完全复用。2.保证了线程的安全。3.避免了参数的传来传去。



采用ThreadLocal维护Connection