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

  1. //$Id: DriverManagerConnectionProvider.java 7888 2005-08-12 21:22:38Z oneovthafew $   
  2.   
  3. package  org.hibernate.connection;  
  4.   
  5.   
  6.   
  7. import  java.sql.Connection;  
  8.   
  9. import  java.sql.DriverManager;  
  10.   
  11. import  java.sql.SQLException;  
  12.   
  13. import  java.util.ArrayList;  
  14.   
  15. import  java.util.Iterator;  
  16.   
  17. import  java.util.Properties;  
  18.   
  19.   
  20.   
  21. import  org.slf4j.Logger;  
  22.   
  23. import  org.slf4j.LoggerFactory;  
  24.   
  25. import  org.hibernate.HibernateException;  
  26.   
  27. import  org.hibernate.cfg.Environment;  
  28.   
  29. import  org.hibernate.util.PropertiesHelper;  
  30.   
  31. import  org.hibernate.util.ReflectHelper;  
  32.   
  33.   
  34.   
  35. /**  
  36.  
  37.  * A connection provider that uses <tt>java.sql.DriverManager</tt>. This provider  
  38.  
  39.  * also implements a very rudimentary connection pool.  
  40.  
  41.  * @see ConnectionProvider  
  42.  
  43.  * @author Gavin King  
  44.  
  45.  */   
  46.   
  47. public   class  DriverManagerConnectionProvider  implements  ConnectionProvider {  
  48.   
  49.   
  50.   
  51.     private  String url;  
  52.   
  53.     private  Properties connectionProps;  
  54.   
  55.     private  Integer isolation;  
  56.   
  57.     private   final  ArrayList pool =  new  ArrayList();  
  58.   
  59.     private   int  poolSize;  
  60.   
  61.     private   int  checkedOut =  0 ;  
  62.   
  63.     private   boolean  autocommit;  
  64.   
  65.   
  66.   
  67.     private   static   final  Logger log = LoggerFactory.getLogger(DriverManagerConnectionProvider. class );  
  68.   
  69.   
  70.   
  71.     public   void  configure(Properties props)  throws  HibernateException {  
  72.   
  73.   
  74.   
  75.         String driverClass = props.getProperty(Environment.DRIVER);  
  76.   
  77.   
  78.   
  79.         poolSize = PropertiesHelper.getInt(Environment.POOL_SIZE, props, 20 );  //default pool size 20   
  80.   
  81.         log.info("Using Hibernate built-in connection pool (not for production use!)" );  
  82.   
  83.         log.info("Hibernate connection pool size: "  + poolSize);  
  84.   
  85.           
  86.   
  87.         autocommit = PropertiesHelper.getBoolean(Environment.AUTOCOMMIT, props);  
  88.   
  89.         log.info("autocommit mode: "  + autocommit);  
  90.   
  91.   
  92.   
  93.         isolation = PropertiesHelper.getInteger(Environment.ISOLATION, props);  
  94.   
  95.         if  (isolation!= null )  
  96.   
  97.         log.info( "JDBC isolation level: "  + Environment.isolationLevelToString( isolation.intValue() ) );  
  98.   
  99.   
  100.   
  101.         if  (driverClass== null ) {  
  102.   
  103.             log.warn("no JDBC Driver class was specified by property "  + Environment.DRIVER);  
  104.   
  105.         }  
  106.   
  107.         else  {  
  108.   
  109.             try  {  
  110.   
  111.                 // trying via forName() first to be as close to DriverManager's semantics   
  112.   
  113.                 Class.forName(driverClass);  
  114.   
  115.             }  
  116.   
  117.             catch  (ClassNotFoundException cnfe) {  
  118.   
  119.                 try  {  
  120.   
  121.                     ReflectHelper.classForName(driverClass);  
  122.   
  123.                 }  
  124.   
  125.                 catch  (ClassNotFoundException e) {  
  126.   
  127.                     String msg = "JDBC Driver class not found: "  + driverClass;  
  128.   
  129.                     log.error( msg, e );  
  130.   
  131.                     throw   new  HibernateException(msg, e);  
  132.   
  133.                 }  
  134.   
  135.             }  
  136.   
  137.         }  
  138.   
  139.   
  140.   
  141.         url = props.getProperty( Environment.URL );  
  142.   
  143.         if  ( url ==  null  ) {  
  144.   
  145.             String msg = "JDBC URL was not specified by property "  + Environment.URL;  
  146.   
  147.             log.error( msg );  
  148.   
  149.             throw   new  HibernateException( msg );  
  150.   
  151.         }  
  152.   
  153.   
  154.   
  155.         connectionProps = ConnectionProviderFactory.getConnectionProperties( props );  
  156.   
  157.   
  158.   
  159.         log.info( "using driver: "  + driverClass +  " at URL: "  + url );  
  160.   
  161.         // if debug level is enabled, then log the password, otherwise mask it   
  162.   
  163.         if  ( log.isDebugEnabled() ) {  
  164.   
  165.             log.info( "connection properties: "  + connectionProps );  
  166.   
  167.         }   
  168.   
  169.         else   if  ( log.isInfoEnabled() ) {  
  170.   
  171.             log.info( "connection properties: "  + PropertiesHelper.maskOut(connectionProps,  "password" ) );  
  172.   
  173.         }  
  174.   
  175.   
  176.   
  177.     }  
  178.   
  179.   
  180.   
  181.     public  Connection getConnection()  throws  SQLException {  
  182.   
  183.   
  184.   
  185.         if  ( log.isTraceEnabled() ) log.trace(  "total checked-out connections: "  + checkedOut );  
  186.   
  187.   
  188.   
  189.         synchronized  (pool) {  
  190.   
  191.             if  ( !pool.isEmpty() ) {  
  192.   
  193.                 int  last = pool.size() -  1 ;  
  194.   
  195.                 if  ( log.isTraceEnabled() ) {  
  196.   
  197.                     log.trace("using pooled JDBC connection, pool size: "  + last);  
  198.   
  199.                     checkedOut++;  
  200.   
  201.                 }  
  202.   
  203.                 Connection pooled = (Connection) pool.remove(last);  
  204.   
  205.                 if  (isolation!= null ) pooled.setTransactionIsolation( isolation.intValue() );  
  206.   
  207.                 if  ( pooled.getAutoCommit()!=autocommit ) pooled.setAutoCommit(autocommit);  
  208.   
  209.                 return  pooled;  
  210.   
  211.             }  
  212.   
  213.         }  
  214.   
  215.   
  216.   
  217.         log.debug("opening new JDBC connection" );  
  218.   
  219.         Connection conn = DriverManager.getConnection(url, connectionProps);  
  220.   
  221.         if  (isolation!= null ) conn.setTransactionIsolation( isolation.intValue() );  
  222.   
  223.         if  ( conn.getAutoCommit()!=autocommit ) conn.setAutoCommit(autocommit);  
  224.   
  225.   
  226.   
  227.         if  ( log.isDebugEnabled() ) {  
  228.   
  229.             log.debug( "created connection to: "  + url +  ", Isolation Level: "  + conn.getTransactionIsolation() );  
  230.   
  231.         }  
  232.   
  233.         if  ( log.isTraceEnabled() ) checkedOut++;  
  234.   
  235.   
  236.   
  237.         return  conn;  
  238.   
  239.     }  
  240.   
  241.   
  242.   
  243.     public   void  closeConnection(Connection conn)  throws  SQLException {  
  244.   
  245.   
  246.   
  247.         if  ( log.isDebugEnabled() ) checkedOut--;  
  248.   
  249.   
  250.   
  251.         synchronized  (pool) {  
  252.   
  253.             int  currentSize = pool.size();  
  254.   
  255.             if  ( currentSize < poolSize ) {  
  256.   
  257.                 if  ( log.isTraceEnabled() ) log.trace( "returning connection to pool, pool size: "  + (currentSize +  1 ) );  
  258.   
  259.                 pool.add(conn);  
  260.   
  261.                 return ;  
  262.   
  263.             }  
  264.   
  265.         }  
  266.   
  267.   
  268.   
  269.         log.debug("closing JDBC connection" );  
  270.   
  271.   
  272.   
  273.         conn.close();  
  274.   
  275.   
  276.   
  277.     }  
  278.   
  279.   
  280.   
  281.     protected   void  finalize() {  
  282.   
  283.         close();  
  284.   
  285.     }  
  286.   
  287.   
  288.   
  289.     public   void  close() {  
  290.   
  291.   
  292.   
  293.         log.info("cleaning up connection pool: "  + url);  
  294.   
  295.   
  296.   
  297.         Iterator iter = pool.iterator();  
  298.   
  299.         while  ( iter.hasNext() ) {  
  300.   
  301.             try  {  
  302.   
  303.                 ( (Connection) iter.next() ).close();  
  304.   
  305.             }  
  306.   
  307.             catch  (SQLException sqle) {  
  308.   
  309.                 log.warn("problem closing pooled connection" , sqle);  
  310.   
  311.             }  
  312.   
  313.         }  
  314.   
  315.         pool.clear();  
  316.   
  317.   
  318.   
  319.     }  
  320.   
  321.   
  322.   
  323.     /**  
  324.  
  325.      * @see ConnectionProvider#supportsAggressiveRelease()  
  326.  
  327.      */   
  328.   
  329.     public   boolean  supportsAggressiveRelease() {  
  330.   
  331.         return   false ;  
  332.   
  333.     }  
  334.   
  335.   
  336.   
  337. }  

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

  1.   < property   name = "connection.driver_class" > com.mysql.jdbc.Driver </ property >   
  2.   
  3.   
  4.   
  5.   
  6.   
  7. <!-- 连接数据库的URL-->   
  8.   
  9.   
  10.   
  11. < property   name = "connection.url" >    
  12.   
  13.   
  14.   
  15. jdbc:mysql://localhost:3306/schoolproject  
  16.   
  17.   
  18.   
  19. </ property >   
  20.   
  21.   
  22.   
  23. < property   name = "connection.useUnicode" > true </ property >   
  24.   
  25.   
  26.   
  27. < property   name = "connection.characterEncoding" > UTF-8 </ property >   
  28.   
  29.   
  30.   
  31.   
  32.   
  33. <!--连接的登录名-->   
  34.   
  35.   
  36.   
  37. < property   name = "connection.username" > root </ property >   
  38.   
  39.   
  40.   
  41.   
  42.   
  43. <!—登录密码-->   
  44.   
  45.   
  46.   
  47. < property   name = "connection.password" > </ property >   
  48.   
  49.   
  50.   
  51.   
  52.   
  53. <!--是否将运行期生成的SQL输出到日志以供调试-->   
  54.   
  55.   
  56.   
  57. < property   name = "show_sql" > true </ property >   
  58.   
  59.   
  60.   
  61.   
  62.   
  63. <!--指定连接的语言-->   
  64.   
  65.   
  66.   
  67. < property   name = "dialect" > org.hibernate.dialect.MySQLDialect </ property >   

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

  C3P0连接配置

  1. <!—JDBC驱动程序-- >   
  2.   
  3.   
  4.   
  5. < property   name = "connection.driver_class" > com.mysql.jdbc.Driver </ property >   
  6.   
  7.   
  8.   
  9. <!-- 连接数据库的URL-->   
  10.   
  11.   
  12.   
  13. < property   name = "connection.url" >    
  14.   
  15.   
  16.   
  17. jdbc:mysql://localhost:3306/schoolproject  
  18.   
  19.   
  20.   
  21. </ property >   
  22.   
  23.   
  24.   
  25. < property   name = "connection.useUnicode" > true </ property >   
  26.   
  27.   
  28.   
  29. < property   name = "connection.characterEncoding" > UTF-8 </ property >   
  30.   
  31.   
  32.   
  33. <!--连接的登录名-->   
  34.   
  35.   
  36.   
  37. < property   name = "connection.username" > root </ property >   
  38.   
  39.   
  40.   
  41. <!--登录密码-->   
  42.   
  43.   
  44.   
  45. < property   name = "connection.password" > </ property >   
  46.   
  47.   
  48.   
  49. <!-- C3P0连接池设定-->   
  50.   
  51.   
  52.   
  53. < property   name = "hibernate.connection.provider_class" > org.hibernate.connection.C3P0ConnectionProvider  
  54.   
  55. </ property >   
  56.   
  57.   
  58.   
  59. < property   name = "hibernate.c3p0.max_size" > 20 </ property >   
  60.   
  61.   
  62.   
  63. < property   name = "hibernate.c3p0.min_size" > 5 </ property >   
  64.   
  65.   
  66.   
  67. < property   name = "hibernate.c3p0.timeout" > 120 </ property >   
  68.   
  69.   
  70.   
  71. < property   name = "hibernate.c3p0.max_statements" > 100 </ property >   
  72.   
  73.   
  74.   
  75. < property   name = "hibernate.c3p0.idle_test_period" > 120 </ property >   
  76.   
  77.   
  78.   
  79. < property   name = "hibernate.c3p0.acquire_increment" > 2 </ property >   
  80.   
  81.   
  82.   
  83. <!--是否将运行期生成的SQL输出到日志以供调试-->   
  84.   
  85.   
  86.   
  87. < property   name = "show_sql" > true </ property >   
  88.   
  89.   
  90.   
  91. <!--指定连接的语言-->   
  92.   
  93.   
  94.   
  95. < 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 这个类是留给用户自己扩展的,基本上什么都不干。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值