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