【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还可以在其他很多情况下应用,在后面的使用中再进行说明。
总结
多线程是解决高并发时常用的技术,明确线程之间的资源共享,合理分配并控制好资源之间的协调,便可以用好多线程,也是应用多线程的前提,在这方面还很欠缺,多多积累学习!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。