首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

org.hibernate.connection包分析-DriverManagerConnectionProvider,DatasourceConnect

2012-08-16 
org.hibernate.connection包分析--DriverManagerConnectionProvider,DatasourceConnectview plaincopy to

org.hibernate.connection包分析--DriverManagerConnectionProvider,DatasourceConnect
view plaincopy to clipboardprint?

  1. //$Id:?DriverManagerConnectionProvider.java?7888?2005-08-12?21:22:38Z?oneovthafew?$????
  2. package?org.hibernate.connection;????
  3. ????
  4. import?java.sql.Connection;????
  5. import?java.sql.DriverManager;????
  6. import?java.sql.SQLException;????
  7. import?java.util.ArrayList;????
  8. import?java.util.Iterator;????
  9. import?java.util.Properties;????
  10. ????
  11. import?org.slf4j.Logger;????
  12. import?org.slf4j.LoggerFactory;????
  13. import?org.hibernate.HibernateException;????
  14. import?org.hibernate.cfg.Environment;????
  15. import?org.hibernate.util.PropertiesHelper;????
  16. import?org.hibernate.util.ReflectHelper;????
  17. ????
  18. /**??
  19. ?*?A?connection?provider?that?uses?<tt>java.sql.DriverManager</tt>.?This?provider??
  20. ?*?also?implements?a?very?rudimentary?connection?pool.??
  21. ?*?@see?ConnectionProvider??
  22. ?*?@author?Gavin?King??
  23. ?*/????
  24. public?class?DriverManagerConnectionProvider?implements?ConnectionProvider?{????
  25. ????
  26. ????private?String?url;????
  27. ????private?Properties?connectionProps;????
  28. ????private?Integer?isolation;????
  29. ????private?final?ArrayList?pool?=?new?ArrayList();????
  30. ????private?int?poolSize;????
  31. ????private?int?checkedOut?=?0;????
  32. ????private?boolean?autocommit;????
  33. ????
  34. ????private?static?final?Logger?log?=?LoggerFactory.getLogger(DriverManagerConnectionProvider.class);????
  35. ????
  36. ????public?void?configure(Properties?props)?throws?HibernateException?{????
  37. ????
  38. ????????String?driverClass?=?props.getProperty(Environment.DRIVER);????
  39. ????
  40. ????????poolSize?=?PropertiesHelper.getInt(Environment.POOL_SIZE,?props,?20);?//default?pool?size?20????
  41. ????????log.info("Using?Hibernate?built-in?connection?pool?(not?for?production?use!)");????
  42. ????????log.info("Hibernate?connection?pool?size:?"?+?poolSize);????
  43. ????????????
  44. ????????autocommit?=?PropertiesHelper.getBoolean(Environment.AUTOCOMMIT,?props);????
  45. ????????log.info("autocommit?mode:?"?+?autocommit);????
  46. ????
  47. ????????isolation?=?PropertiesHelper.getInteger(Environment.ISOLATION,?props);????
  48. ????????if?(isolation!=null)????
  49. ????????log.info(?"JDBC?isolation?level:?"?+?Environment.isolationLevelToString(?isolation.intValue()?)?);????
  50. ????
  51. ????????if?(driverClass==null)?{????
  52. ????????????log.warn("no?JDBC?Driver?class?was?specified?by?property?"?+?Environment.DRIVER);????
  53. ????????}????
  54. ????????else?{????
  55. ????????????try?{????
  56. ????????????????//?trying?via?forName()?first?to?be?as?close?to?DriverManager's?semantics????
  57. ????????????????Class.forName(driverClass);????
  58. ????????????}????
  59. ????????????catch?(ClassNotFoundException?cnfe)?{????
  60. ????????????????try?{????
  61. ????????????????????ReflectHelper.classForName(driverClass);????
  62. ????????????????}????
  63. ????????????????catch?(ClassNotFoundException?e)?{????
  64. ????????????????????String?msg?=?"JDBC?Driver?class?not?found:?"?+?driverClass;????
  65. ????????????????????log.error(?msg,?e?);????
  66. ????????????????????throw?new?HibernateException(msg,?e);????
  67. ????????????????}????
  68. ????????????}????
  69. ????????}????
  70. ????
  71. ????????url?=?props.getProperty(?Environment.URL?);????
  72. ????????if?(?url?==?null?)?{????
  73. ????????????String?msg?=?"JDBC?URL?was?not?specified?by?property?"?+?Environment.URL;????
  74. ????????????log.error(?msg?);????
  75. ????????????throw?new?HibernateException(?msg?);????
  76. ????????}????
  77. ????
  78. ????????connectionProps?=?ConnectionProviderFactory.getConnectionProperties(?props?);????
  79. ????
  80. ????????log.info(?"using?driver:?"?+?driverClass?+?"?at?URL:?"?+?url?);????
  81. ????????//?if?debug?level?is?enabled,?then?log?the?password,?otherwise?mask?it????
  82. ????????if?(?log.isDebugEnabled()?)?{????
  83. ????????????log.info(?"connection?properties:?"?+?connectionProps?);????
  84. ????????}?????
  85. ????????else?if?(?log.isInfoEnabled()?)?{????
  86. ????????????log.info(?"connection?properties:?"?+?PropertiesHelper.maskOut(connectionProps,?"password")?);????
  87. ????????}????
  88. ????
  89. ????}????
  90. ????
  91. ????public?Connection?getConnection()?throws?SQLException?{????
  92. ????
  93. ????????if?(?log.isTraceEnabled()?)?log.trace(?"total?checked-out?connections:?"?+?checkedOut?);????
  94. ????
  95. ????????synchronized?(pool)?{????
  96. ????????????if?(?!pool.isEmpty()?)?{????
  97. ????????????????int?last?=?pool.size()?-?1;????
  98. ????????????????if?(?log.isTraceEnabled()?)?{????
  99. ????????????????????log.trace("using?pooled?JDBC?connection,?pool?size:?"?+?last);????
  100. ????????????????????checkedOut++;????
  101. ????????????????}????
  102. ????????????????Connection?pooled?=?(Connection)?pool.remove(last);????
  103. ????????????????if?(isolation!=null)?pooled.setTransactionIsolation(?isolation.intValue()?);????
  104. ????????????????if?(?pooled.getAutoCommit()!=autocommit?)?pooled.setAutoCommit(autocommit);????
  105. ????????????????return?pooled;????
  106. ????????????}????
  107. ????????}????
  108. ????
  109. ????????log.debug("opening?new?JDBC?connection");????
  110. ????????Connection?conn?=?DriverManager.getConnection(url,?connectionProps);????
  111. ????????if?(isolation!=null)?conn.setTransactionIsolation(?isolation.intValue()?);????
  112. ????????if?(?conn.getAutoCommit()!=autocommit?)?conn.setAutoCommit(autocommit);????
  113. ????
  114. ????????if?(?log.isDebugEnabled()?)?{????
  115. ????????????log.debug(?"created?connection?to:?"?+?url?+?",?Isolation?Level:?"?+?conn.getTransactionIsolation()?);????
  116. ????????}????
  117. ????????if?(?log.isTraceEnabled()?)?checkedOut++;????
  118. ????
  119. ????????return?conn;????
  120. ????}????
  121. ????
  122. ????public?void?closeConnection(Connection?conn)?throws?SQLException?{????
  123. ????
  124. ????????if?(?log.isDebugEnabled()?)?checkedOut--;????
  125. ????
  126. ????????synchronized?(pool)?{????
  127. ????????????int?currentSize?=?pool.size();????
  128. ????????????if?(?currentSize?<?poolSize?)?{????
  129. ????????????????if?(?log.isTraceEnabled()?)?log.trace("returning?connection?to?pool,?pool?size:?"?+?(currentSize?+?1)?);????
  130. ????????????????pool.add(conn);????
  131. ????????????????return;????
  132. ????????????}????
  133. ????????}????
  134. ????
  135. ????????log.debug("closing?JDBC?connection");????
  136. ????
  137. ????????conn.close();????
  138. ????
  139. ????}????
  140. ????
  141. ????protected?void?finalize()?{????
  142. ????????close();????
  143. ????}????
  144. ????
  145. ????public?void?close()?{????
  146. ????
  147. ????????log.info("cleaning?up?connection?pool:?"?+?url);????
  148. ????
  149. ????????Iterator?iter?=?pool.iterator();????
  150. ????????while?(?iter.hasNext()?)?{????
  151. ????????????try?{????
  152. ????????????????(?(Connection)?iter.next()?).close();????
  153. ????????????}????
  154. ????????????catch?(SQLException?sqle)?{????
  155. ????????????????log.warn("problem?closing?pooled?connection",?sqle);????
  156. ????????????}????
  157. ????????}????
  158. ????????pool.clear();????
  159. ????
  160. ????}????
  161. ????
  162. ????/**??
  163. ?????*?@see?ConnectionProvider#supportsAggressiveRelease()??
  164. ?????*/????
  165. ????public?boolean?supportsAggressiveRelease()?{????
  166. ????????return?false;????
  167. ????}????
  168. ????
  169. }??
view plaincopy to clipboardprint?
  1. ???

DriverManagerConnectionProvider类继承了ConnectionProvider接口,主要是使用用户提供的JDBC驱动程序来连接数据库,或者使用连接池的方式来连接数据库。 ?? 一个典型的JDBC驱动连接数据库的方式:

view plaincopy to clipboardprint?
  1. ?<property?name="connection.driver_class">com.mysql.jdbc.Driver</property>????
  2. ????
  3. ????
  4. <!--?连接数据库的URL-->????
  5. ????
  6. <property?name="connection.url">?????
  7. ????
  8. jdbc:mysql://localhost:3306/schoolproject????
  9. ????
  10. </property>????
  11. ????
  12. <property?name="connection.useUnicode">true</property>????
  13. ????
  14. <property?name="connection.characterEncoding">UTF-8</property>????
  15. ????
  16. ????
  17. <!--连接的登录名-->????
  18. ????
  19. <property?name="connection.username">root</property>????
  20. ????
  21. ????
  22. <!—登录密码-->????
  23. ????
  24. <property?name="connection.password"></property>????
  25. ????
  26. ????
  27. <!--是否将运行期生成的SQL输出到日志以供调试-->????
  28. ????
  29. <property?name="show_sql">true</property>????
  30. ????
  31. ????
  32. <!--指定连接的语言-->????
  33. ????
  34. <property?name="dialect">org.hibernate.dialect.MySQLDialect</property>??

?至于连接池,由于在hibernate3.0中,已经不再支持dbcp了,hibernate的作者在hibernate.org中,明确指出在实践中发现dbcp有BUG,在某些种情会产生很多空连接不能释放,所以抛弃了对dbcp的支持。因此官方推荐使用c3p0或Proxool连接池。

? C3P0连接配置

view plaincopy to clipboardprint?
  1. <!—JDBC驱动程序-->????
  2. ????
  3. <property?name="connection.driver_class">com.mysql.jdbc.Driver</property>????
  4. ????
  5. <!--?连接数据库的URL-->????
  6. ????
  7. <property?name="connection.url">?????
  8. ????
  9. jdbc:mysql://localhost:3306/schoolproject????
  10. ????
  11. </property>????
  12. ????
  13. <property?name="connection.useUnicode">true</property>????
  14. ????
  15. <property?name="connection.characterEncoding">UTF-8</property>????
  16. ????
  17. <!--连接的登录名-->????
  18. ????
  19. <property?name="connection.username">root</property>????
  20. ????
  21. <!--登录密码-->????
  22. ????
  23. <property?name="connection.password"></property>????
  24. ????
  25. <!--?C3P0连接池设定-->????
  26. ????
  27. <property?name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider????
  28. </property>????
  29. ????
  30. <property?name="hibernate.c3p0.max_size">20</property>????
  31. ????
  32. <property?name="hibernate.c3p0.min_size">5</property>????
  33. ????
  34. <property?name="hibernate.c3p0.timeout">120</property>????
  35. ????
  36. <property?name="hibernate.c3p0.max_statements">100</property>????
  37. ????
  38. <property?name="hibernate.c3p0.idle_test_period">120</property>????
  39. ????
  40. <property?name="hibernate.c3p0.acquire_increment">2</property>????
  41. ????
  42. <!--是否将运行期生成的SQL输出到日志以供调试-->????
  43. ????
  44. <property?name="show_sql">true</property>????
  45. ????
  46. <!--指定连接的语言-->????
  47. ????
  48. <property?name="dialect">org.hibernate.dialect.MySQLDialect</property>??

?  首先看DriverManagerConnectionProvider的configure(Properties props)方法,在这个方法中并没有去判断是否使用了连接池,真正判断使用连接池是在ConnectionProviderFactory这个类中,我们以后会分析。???

  DriverManagerConnectionProvider这个类只是初始化了最基本的连接配置,有如下几个:hibernate.connection.driver_class(JDBC驱动类)、hibernate.connection.pool_size(连接池容量的上限数目)、hibernate.connection.autocommit(允许被缓存的JDBC连接开启自动自动提交)、hibernate.connection.isolation(设置JDBC事务隔离级别,可查看java.sql.Connection来了解各个值的具体意义,但请注意多数数据库都不支持所有的隔离级别,取值1,2,4,8)。无论你是使用JDBC还是使用连接池方式,这几个最基本的设置都是要先初始化的。其中pool_size的默认值为20。

  configure(Properties props)方法中的这个语句connectionProps = ConnectionProviderFactory.getConnectionProperties( props );值得注意, ConnectionProviderFactory.getConnectionProperties( props )主要是把HIBERNATE.CFG或者HIBERNATE.PROPERTIES的配置文件中的属性重新封装到另一个Properties 类——connectionProps中,且connectionProps的键值与 HIBERNATE.CFG或者HIBERNATE.PROPERTIES中的键值相比是没有“hibernate.connection”这样的字样的,比如,在HIBERNATE.PROPERTIES中定义的“hibernate.connection.pool_size”属性键,到该Properties 类 中的键就成了“pool_size ”。connectionProps主要是为后面的getConnection()方法而提供的。 ??

  接下来是getConnection()方法,在这里我们发现了synchronized关键字,这个关键字是加在pool这个对象上的,也就是说某个时刻只有其中的一个线程可以访问这个对象的synchronized数据。每个对象都有一个"锁标志",当这个对象的一个线程访问这个对象的某个synchronized数据时,这个对象的所有被synchronized修饰的数据将被上锁(因为"锁标志"被当前线程拿走了),只有当前线程访问完它要访问的synchronized数据时,当前线程才会释放"锁标志",这样同一个对象的其它线程才有机会访问synchronized数据。pool是什么?它是一个ArrayList,也就是连接池,里面都是一个个的Connection对象,这个可以在后面的closeConnection(Connection conn)体现出来,正在pool上加synchronized修饰符就保证了多个线程不能并发访问此ArrayList而生成不正确的结果。当调用getConnection()方法时,我们可以看到连接池就移除了一个连接。

  Connection conn = DriverManager.getConnection(url, connectionProps)语句中我们可以看到全局变量connectionProps是传入到了这个方法中的,返回了一个Connection 对象。 ??

  ?closeConnection(Connection conn)方法是将连接重新放回到连接池。 ??

  close()方法清空了连接池,关闭所有连接。 ??

  supportsAggressiveRelease()方法返回的是false,表示连接释放模式会被设置为hibernate.connection.release_mode.AFTER_TRANSACTION也就是说在org.hibernate.Transaction结束后释放连接。

DatasourceConnectionProvider类分析 ?? DatasourceConnectionProvider类比较简单,不同的是,它通过JNDI的方式来查找数据源来获得连接,这个类中要注意的方法是supportsAggressiveRelease()它返回的是true,表示在使用数据源连接的情况下,支持使用hibernate.connection.release_mode.AFTER_STATEMENT这一个设置。

UserSuppliedConnectionProvider类分析 ?? UserSuppliedConnectionProvider 这个类是留给用户自己扩展的,基本上什么都不干。

热点排行