【Java技术点滴】——ThreadLocal封装JDBC事务操作

背景

    在Java程序实现中,我们往往应用到事务的机制,在业务层进行事务开启,创建数据库连接,调用Dao层方法进行数据库访问,过程中需要将数据库连接Connection作为参数传递给Dao层方法。显而易见,这样的实现不利于Dao层方法的复用,当在不使用事务的情况下,我们是需要在Dao层方法中创建数据库连接的,这样Dao层方法免去Connection参数就可以使得方法更加独立、明确了,怎样解决这样的尴尬?对于此,我们使用了ThreadLocal进行解决。

基本介绍

    “本地线程变量”,可以理解为将变量放到ThreadLocal中,同一个线程中共享,多线程之间资源隔离,不相互干扰,保证了线程安全。
    可将ThreadLocal<T>看作是一个Map类型,可以理解为以存取键值对的方式进行存和取,但需要明确一点的是确定了一个ThreadLocal后,其中就只能存取一个键值对,因此其读和取方法也比较简单了:
    get、set方法--为读取、设置线程变量中的值;
    remove方法  --移除此线程局部变量当前线程的值;
    initialValue--返回此线程局部变量的当前线程初始值。

封装Connection

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 {

	//定义ThreadLocal静态变量,确定存取类型为Connection
	private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();
	
	/**
	 * 得到Connection
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = connectionHolder.get();
		//如果在当前线程中没有绑定相应的Connection
		if (conn == null) {
			try {
				Class.forName("oracle.jdbc.driver.OracleDriver");
				String url = "jdbc:oracle:thin:@localhost:1521:bjpowern";
				String username = "drp1";
				String password = "drp1";
				conn = DriverManager.getConnection(url, username, password);
				//将Connection设置到ThreadLocal
				connectionHolder.set(conn);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return conn;
	}
	
	/**
	 * 关闭数据库连接方法
	 * @return
	 */
	public static void closeConnection() {
		Connection conn = connectionHolder.get();
		if (conn != null) {
			try {
				conn.close();
				//从ThreadLocal中清除Connection
				connectionHolder.remove();
			} catch (SQLException e) {
				e.printStackTrace();
			}	
		}
	}
	
	/**
	 * 关闭数据库连接方法
	 * @return
	 */
	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();
			}
		}
	}
	
	/**
	 * 事务开启
	 * @return
	 */
	public static void beginTransaction(Connection conn) {
		try {
			if (conn != null) {
				if (conn.getAutoCommit()) {
					conn.setAutoCommit(false); //手动提交
				}
			}
		}catch(SQLException e) {}
	}
	
	/**
	 * 事务提交
	 * @return
	 */
	public static void commitTransaction(Connection conn) {
		try {
			if (conn != null) {
				if (!conn.getAutoCommit()) {
					conn.commit();
				}
			}
		}catch(SQLException e) {}
	}
	
	/**
	 * 事务回滚
	 * @return
	 */
	public static void rollbackTransaction(Connection conn) {
		try {
			if (conn != null) {
				if (!conn.getAutoCommit()) {
					conn.rollback();
				}
			}
		}catch(SQLException e) {}
	}	
}

    经过了以上的封装,ConnectionManager类控制了线程内Connection的创建与获取,就达到了Dao层方法不需要传递Connection参数便可实现业务逻辑层控制事务的效果,ThreadLocal还可以在其他很多情况下应用,在后面的使用中再进行说明。


总结

    多线程是解决高并发时常用的技术,明确线程之间的资源共享,合理分配并控制好资源之间的协调,便可以用好多线程,也是应用多线程的前提,在这方面还很欠缺,多多积累学习!


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。