文章导读:
讲解了一个线程为什么要使用同一个connection, 我们分析了HiberatenSessionFactory的实现机制, 然后根据Hibernate的写法重构了我们的代码. 最后测试可以发现在同一个线程中只能得到同一个Connection.
视频与源码下载:http://edu.51cto.com/lecturer/index/user_id-9166337.html (代码在视频的附件中)
HibernateSessionFactory源码分析加载配置文件
1 // 加载配置文件,返回SessionFactory 2 static { 3 try { 4 configuration.configure(configFile); 5 // 构建sessionFactory并且返回 6 sessionFactory = configuration.buildSessionFactory(); 7 } catch (Exception e) { 8 System.err.println("%%%% Error Creating SessionFactory %%%%"); 9 e.printStackTrace(); 10 } 11 }
同一个线程获取同一个Session对象,就是采用ThreadLocal来实现的
1 // 同一个线程获取同一个session对象 2 public static Session getSession() throws HibernateException { 3 // 查询当前threadLocal是否已存在session 4 Session session = (Session) threadLocal.get(); 5 // 判断当前session是否可以使用 6 if (session == null || !session.isOpen()) { 7 // 如果sessionFactory不为空,则新创建一个session 8 session = (sessionFactory != null) ? sessionFactory.openSession(): null; 9 // 把创建的session存放到threadLocal中,这样就可以保证一个线程公用一个session 10 threadLocal.set(session); 11 } 12 // 返回session 13 return session; 14 }
关闭Session的实现
1 // 关闭不需要传入session,只需要到threadLocal去获取 2 public static void closeSession() throws HibernateException { 3 Session session = (Session) threadLocal.get(); 4 threadLocal.set(null); 5 if (session != null) { 6 session.close(); 7 } 8 }
根据源码分析重构我们自己的Connection
1 // 获取connection链接对象 2 public static Connection getConnection() { 3 Connection connection = threadLocal.get(); 4 try { 5 // 当前conn不存在,或者已经关闭 6 if (connection == null || connection.isClosed()) { 7 connection = DriverManager.getConnection( 8 "jdbc:mysql://127.0.0.1:3306/demo", "root", "root"); 9 threadLocal.set(connection); 10 } 11 12 return connection; 13 } catch (SQLException e) { 14 throw new RuntimeException(e); 15 } 16 }
重构后测试结果如下:
1 public static void main(String[] args) { 2 // 一个线程一个Session方便后期事务实现 3 System.out.println(JdbcUtils.getConnection()); 4 System.out.println(JdbcUtils.getConnection()); 5 }
测试结果如下(一个线程同一个Conneciton)
1 com.mysql.jdbc.JDBC4Connection@7bb52a38 2 com.mysql.jdbc.JDBC4Connection@7bb52a38