`
Dustin
  • 浏览: 310533 次
  • 性别: Icon_minigender_1
  • 来自: 广州/成都
社区版块
存档分类
最新评论

使用JDBC时Class.forName()的作用

阅读更多

    使用JDBC时,我们都会很自然得使用下列语句:

java 代码
  1. Class.forName("com.mysql.jdbc.Driver");   
  2. String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";   
  3. String user = "";   
  4. String psw = "";   
  5. Connection con = DriverManager.getConnection(url,user,psw);  


    为什么说很自然呢,因为无论是网上还是书本教程上得例子都是这样的,而且程序也确实正常运行了,于是大家也就心安理得的找葫芦画瓢下去了。
    一定要有这一句吗?不是的,我们完全可以用这样一句代替它:

java 代码
  1. com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver();   
  2. //or:   
  3. //new com.mysql.jdbc.Driver();   
  4. String url = "jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8";   
  5. String user = "";   
  6. String psw = "";   
  7. Connection con = DriverManager.getConnection(url,user,psw);   
  8.   

    大家可能都看出个大概来了,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。上面两种方法都可以实现这个功能,因此程序可以正常运行。注意了,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。

java 代码
  1. com.mysql.jdbc.Driver driver = null;   
  2. //or:   
  3. ClassLoader cl = new ClassLoader();   
  4. cl.loadClass("com.mysql.jdbc.Driver");  


     我们都知道JDBC是使用Bridge模式进行设计的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现(请参考GOF的Bridge模式的描述)。大家注意了,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。
     Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去啊,这是怎么回事呢?jdk文档对Driver的描述中有这么一句:
     When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager
哦,原来是com.mysql.jdbc.Driver在装载完后自动帮我们完成了这一步骤。源代码是这样的:

java 代码
  1. package com.mysql.jdbc   
  2.   
  3. public class Driver extends NonRegisteringDriver implements java.sql.Driver {   
  4.  // ~ Static fields/initializers   
  5.  // --------------------------------------------- //   
  6.  // Register ourselves with the DriverManager   
  7.  //   
  8.  static {   
  9.     t ry {   
  10.               java.sql.DriverManager.registerDriver(new Driver());   
  11.           } catch (SQLException E) {   
  12.               throw new RuntimeException("Can't register driver!");   
  13.           }   
  14.   }   
  15. // ~ Constructors   
  16.  // -----------------------------------------------------------   
  17. /**  
  18.   * Construct a new driver and register it with DriverManager  
  19.   *   
  20.   * @throws SQLException  
  21.   *             if a database error occurs.  
  22.   */  
  23.  public Driver() throws SQLException {   
  24.      // Required for Class.forName().newInstance()   
  25.  }   
  26. }  
分享到:
评论
14 楼 lgh1992314 2017-06-14  
Godlikeme 写道
<div class='quote_div'>
<p>to 楼上的楼上 Class.forName和 ClassLoader.loadClass是两码事,一个实例化类,一个加载类,不好混到一起说。</p>
</div>

Class.forName(className)方法,内部实际调用的方法是  Class.forName(className,true,classloader);

第2个boolean参数表示类是否需要初始化,  Class.forName(className)默认是需要初始化。

一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。

   

ClassLoader.loadClass(className)方法,内部实际调用的方法是  ClassLoader.loadClass(className,false);

第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,

不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行
13 楼 lgh1992314 2017-06-14  
Class.forName("com.mysql.jdbc.Driver");  
压根就可以不加
12 楼 sandaobusi 2015-03-08  
nkd2002 写道
“我们完全可以用这样一句代替它:”
博主这名句话有错误,第二段代码不能代替第一段,原因请参考http://www.ibm.com/developerworks/cn/java/j-lo-classloader/


第二段理论上不能代替第一段,但是在这种情况下是可以代替的。只要执行了static块就好
11 楼 nkd2002 2014-05-16  
“我们完全可以用这样一句代替它:”
博主这名句话有错误,第二段代码不能代替第一段,原因请参考http://www.ibm.com/developerworks/cn/java/j-lo-classloader/
10 楼 topcoder_lin 2014-05-14  
写的很好!!!!
9 楼 ie4119 2013-12-27  

hello world!   说的太棒了!

8 楼 851228082 2013-12-19  
写的真好,我昨天一直在思考这个问题,单单一个class.forName或者直接new一个Driver,就搞定了,drivermanager怎么就知道调用这个mysql的driver,读完此文一切都明白了。[size=small][/size]
7 楼 shhyuhan 2012-09-25  
受教了。字数补丁
6 楼 Godlikeme 2007-01-11  
<div class='quote_div'>
<p>to 楼上的楼上 Class.forName和 ClassLoader.loadClass是两码事,一个实例化类,一个加载类,不好混到一起说。</p>
</div>
5 楼 huangpengxiao 2007-01-11  
嗯,受教
4 楼 jacshan 2007-01-10  
<br/>
<strong>Dustin 写道:</strong><br/>
<div class='quote_div'>
<p>    使用JDBC时,我们都会很自然得使用下列语句:</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
    <li class='alt'><span><span>Class.forName(</span><span class='string'>"com.mysql.jdbc.Driver"</span><span>);   </span></span> </li>
    <li class=''><span>String url = </span><span class='string'>"jdbc:mysql://127.0.0.1/test?useUnicode=true&amp;characterEncoding=utf-8"</span><span>;   </span> </li>
    <li class='alt'><span>String user = </span><span class='string'>""</span><span>;   </span> </li>
    <li class=''><span>String psw = </span><span class='string'>""</span><span>;   </span> </li>
    <li class='alt'><span>Connection con = DriverManager.getConnection(url,user,psw);  </span> </li>
</ol>
</div>
<p><br/>
    为什么说很自然呢,因为无论是网上还是书本教程上得例子都是这样的,而且程序也确实正常运行了,于是大家也就心安理得的找葫芦画瓢下去了。<br/>
    一定要有这一句吗?不是的,我们完全可以用这样一句代替它:<br/>
</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
    <li class='alt'><span><span>com.mysql.jdbc.Driver driver = </span><span class='keyword'>new</span><span> com.mysql.jdbc.Driver();   </span></span> </li>
    <li class=''><span/><span class='comment'>//or: </span><span>  </span> </li>
    <li class='alt'><span/><span class='comment'>//new com.mysql.jdbc.Driver(); </span><span>  </span> </li>
    <li class=''><span>String url = </span><span class='string'>"jdbc:mysql://127.0.0.1/test?useUnicode=true&amp;characterEncoding=utf-8"</span><span>;   </span> </li>
    <li class='alt'><span>String user = </span><span class='string'>""</span><span>;   </span> </li>
    <li class=''><span>String psw = </span><span class='string'>""</span><span>;   </span> </li>
    <li class='alt'><span>Connection con = DriverManager.getConnection(url,user,psw);   </span> </li>
    <li class=''><span>  </span> </li>
</ol>
</div>
<br/>
<p>    大家可能都看出个大概来了,我们只需要在调用DriverManager的getConnection方法之前,保证相应的Driver类已经被加载到jvm中,并且完成了类的初始化工作就行了,而具体是怎样实现这个功能却是没有讲究的。上面两种方法都可以实现这个功能,因此程序可以正常运行。注意了,如果我们进行如下操作,程序是不能正常运行的,因为这样仅仅使Driver类被装载到jvm中,却没有进行相应的初始化工作。</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
    <li class='alt'><span><span>com.mysql.jdbc.Driver driver = </span><span class='keyword'>null</span><span>;   </span></span> </li>
    <li class=''><span/><span class='comment'>//or: </span><span>  </span> </li>
    <li class='alt'><span>ClassLoader cl = </span><span class='keyword'>new</span><span> ClassLoader();   </span> </li>
    <li class=''><span>cl.loadClass(</span><span class='string'>"com.mysql.jdbc.Driver"</span><span>);  </span> </li>
</ol>
</div>
<p><br/>
     我们都知道JDBC是使用Bridge模式进行设计的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一个具体实现(请参考GOF的Bridge模式的描述)。大家注意了,前一个Driver是一个接口,后者却是一个类,它实现了前面的Driver接口。<br/>
     Bridge模式中,Abstraction(DriverManager)是要拥有一个Implementor(Driver)的引用的,但是我们在使用过程中,并没有将Driver对象注册到DriverManager中去啊,这是怎么回事呢?jdk文档对Driver的描述中有这么一句:<br/>
     <strong>When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager <br/>
</strong>哦,原来是com.mysql.jdbc.Driver在装载完后自动帮我们完成了这一步骤。源代码是这样的:</p>
<div class='code_title'>java 代码</div>
<div class='dp-highlighter'>
<div class='bar'/>
<ol class='dp-j'>
    <li class='alt'><span><span class='keyword'>package</span><span> com.mysql.jdbc   </span></span> </li>
    <li class=''><span>  </span> </li>
    <li class='alt'><span/><span class='keyword'>public</span><span> </span><span class='keyword'>class</span><span> Driver </span><span class='keyword'>extends</span><span> NonRegisteringDriver </span><span class='keyword'>implements</span><span> java.sql.Driver {   </span> </li>
    <li class=''><span> </span><span class='comment'>// ~ Static fields/initializers </span><span>  </span> </li>
    <li class='alt'><span> </span><span class='comment'>// --------------------------------------------- // </span><span>  </span> </li>
    <li class=''><span> </span><span class='comment'>// Register ourselves with the DriverManager </span><span>  </span> </li>
    <li class='alt'><span> </span><span class='comment'>// </span><span>  </span> </li>
    <li class=''><span> </span><span class='keyword'>static</span><span> {   </span> </li>
    <li class='alt'><span>    t ry {   </span> </li>
    <li class=''><span>              java.sql.DriverManager.registerDriver(</span><span class='keyword'>new</span><span> Driver());   </span> </li>
    <li class='alt'><span>          } </span><span class='keyword'>catch</span><span> (SQLException E) {   </span> </li>
    <li class=''><span>              </span><span class='keyword'>throw</span><span> </span><span class='keyword'>new</span><span> RuntimeException(</span><span class='string'>"Can't register driver!"</span><span>);   </span> </li>
    <li class='alt'><span>          }   </span> </li>
    <li class=''><span>  }   </span> </li>
    <li class='alt'><span/><span class='comment'>// ~ Constructors </span><span>  </span> </li>
    <li class=''><span> </span><span class='comment'>// ----------------------------------------------------------- </span><span>  </span> </li>
    <li class='alt'><span/><span class='comment'>/** </span>  </li>
    <li class=''><span><span class='comment'>  * Construct a new driver and register it with DriverManager </span> </span> </li>
    <li class='alt'><span><span class='comment'>  *  </span> </span> </li>
    <li class=''><span><span class='comment'>  * @throws SQLException </span> </span> </li>
    <li class='alt'><span><span class='comment'>  *             if a database error occurs. </span> </span> </li>
    <li class=''><span><span class='comment'>  */</span><span>  </span></span> </li>
    <li class='alt'><span> </span><span class='keyword'>public</span><span> Driver() </span><span class='keyword'>throws</span><span> SQLException {   </span> </li>
    <li class=''><span>     </span><span class='comment'>// Required for Class.forName().newInstance() </span><span>  </span> </li>
    <li class='alt'><span> }   </span> </li>
    <li class=''><span>}  </span> </li>
</ol>
</div>
</div>
<p><br/>
这里ClassLoader为什么不行,是类加载器的机制决定的 <a href='http://www.iteye.com/topic/25053'>www.iteye.com/topic/25053<strong/></a></p>
<p><strong>static块在什么时候执行?</strong> <br/>
1)当调用forName(String)载入class时执行,如果调用ClassLoader.loadClass并不会执行.forName(String,false,ClassLoader)时也不会执行. <br/>
2)如果载入Class时没有执行static块则在第一次实例化时执行.比如new ,Class.newInstance()操作 <br/>
3)static块仅执行一次</p>
<p><br/>
<br/>
<br/>
 </p>
3 楼 liangguanhui 2007-01-10  
其实只要自己写一个Driver的代理就会对这个比较熟
2 楼 Dustin 2007-01-08  
看来我的题目有点以偏概全了:)
complystill从宏观上道出了Class.forName()的作用,我主要是从微观上进行考量的
1 楼 歆渊 2007-01-08  
Class.forName(); 的好处在于你不用编译/运行时依赖于特定的 JDBC Driver 库, 也就减少了项目代码的依赖性. 而且也很容易改造成从配置文件读取JDBC配置, 从而可以在运行时动态更换JDBC/DB.

非M$系的书上和文章里多数这样写,应该因为是从读配置文件初始化JDBC的代码简化来的.

M$系的文章和教材经常是 Driver d = new XXXDriver(); 多半是保证Vendor-Lockin的传统习俗.

相关推荐

    jdbc中class.forname的作用

    主要介绍了jdbc中class.forname的作用,使用示例说明了他作用及使用方法,大家参考使用吧

    sun.jdbc.odbc.JdbcOdbcDriver下载

    jdbc-odbc驱动包,提示找不到驱动,java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver, 原因:从jdk从1.8开始,删除了jdbc-odbc桥,所以odbc的驱动是用不了的 解决方法:这里为提供一个解决JDK1.8不...

    浅析使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")

    主要介绍了使用JDBC操作MySQL需要添加Class.forName("com.mysql.jdbc.Driver")的相关知识,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下

    java连接多种数据库的驱动

    java连接各种数据库的驱动 jar包 orale: Class.forName("oracle.jdbc.driver.OracleDriver"); mysql:Class.forName("com.mysql.jdbc.Driver"); access:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); sqlsever:...

    jdbc驱动程序实例

    //或者Class.forName("com.mysql.jdbc.Driver"); String url ="jdbc:mysql://localhost/myDB? user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" //myDB为数据库名 Connection conn= ...

    注册驱动:Class.forName(xxx.Driver).xmind

    对SPI,理论联系实际的理解

    jdbc.class

    jdbc连接jdbc.class 可用于记事版 与数据库连接

    浅析使用JDBC操作MySQL需要添加Class.forName(“com.mysql.jdbc.Driver”)

    如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据Class.forName (com.mysql.jdbc.Driver); public static Connection getConnection() throws ClassNotFoundException, SQLException ...

    jdbc--sqljdbc4-2.0.jar

    java链接sqlserver数据库包如下错误时: java.lang.ClassNotFoundException: ... at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) 添加sqljdbc4-2.0包即可

    sql jdbc 2.0.1607.1 UNIX

    Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...

    jdbc笔记整理 sql

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000 数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2 数据库 Class.froName(...

    hive-jdbc-2.1.0-standalone.jar

    at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at com.trs.gateway.commons.hive.HiveFeature.getConnection(HiveFeature.java:55) ... 8 more

    JDBC连接各种数据代码.doc

    Class.forName( "oracle.jdbc.driver.OracleDriver" ); con = DriverManager.getConnection( "jdbc:oracle:thin:@127.0.0.1:1521:ORCL", "scott", ”tiger”); 连接SqlServer2000 msbase.jar ...

    Oracle数据库的JDBC驱动包

    其中classes12.jar是从oracle安装目录中获取的,使用它编写java程序连接oracle时,驱动包的加载路径为"oracle.jdbc.driver.OracleDriver",即Class.forName("oracle.jdbc.driver.OracleDriver")。另一个ojdbc6.jar的...

    sqljdbc_sqljdbc4.zip

    Java连接SQL server数据库驱动,文件包含sqljdb和sqljdbc4 ...sqljdbc:Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); sqljdbc4:Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

    Java使用JDBC连接数据库.docx

    使用JDBC-ODBC桥驱动程序连接数据库 基本步骤: ...o(2)通过DriverManager获取数据库连接 o(3)通过Connection对象获取Statement对象 o(4)使用Statement接口执行SQL语句 ...Class.forName("DriverName");

    java连接数据库字符串

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2数据库 Class....

    Java使用数据源配置数据库.rar

      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //装载数据库驱动   Connection con=DriverManager.getConnection(dbURL,user,password); //得到连接   System.out.println(con.getCatalog()); //打印...

    sql jdbc 2.0

    Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...

    Access_JDBC30.jar --Java JDK1.8实现与Access数据库连接

    Java写了一个连接Access数据库... Class.forName("com.hxtt.sql.access.AccessDriver").newInstance(); url = "jdbc:Access:///D:/dataAnalysis/accessDB.mdb"; connect = DriverManager.getConnection(url, "", "");

Global site tag (gtag.js) - Google Analytics