`

JDBC在getConnection之前为什么要调用Class.forName

 
阅读更多

获取一个数据库连接的通用模板如下:

String driver = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String user = "scott";
String password = "ticmy";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);

里面有个Class.forName(driver),这句话有什么作用?将驱动类load到内存?如果没有这句会怎么样?运行发现,如果去掉这一句会有以下异常:
java.sql.SQLException: No suitable driver found for xxx….

在解释具体原因之前先简单看下Class.forName做了什么。

假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情:
1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象
2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系)
3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static块。(这一步是要点)

Class.forName(String className)方法会将这三步都做掉,如下面的例子:

package com.ticmy.oracle;
 
public class TestClinit {
    public static void main(String[] args) throws Exception {
        Class.forName("com.ticmy.oracle.ABC");
    }
}
class ABC {
    private static int a = getNum();
    static {
        System.out.println("this is static block");
    }
    public static int getNum() {
        System.out.println("getNum");
        return 1;
    }
}

程序的运行结果是:
getNum
this is static block

那么,Class.forName(driver)这个driver类里有没有什么static块呢?去探究一下。例子用的是Oracle,反编译下oracle.jdbc.OracleDriver,发现其继承了oracle.jdbc.driver.OracleDriver,那么继续看这个oracle.jdbc.driver.OracleDriver,确实有个static块,里面有这样的代码:

static {
    Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
    try {
      if (defaultDriver == null) {
        defaultDriver = new OracleDriver();
        DriverManager.registerDriver(defaultDriver);
      }
    } catch (RuntimeException localRuntimeException) {
    } catch (SQLException localSQLException){}
    _Copyright_2004_Oracle_All_Rights_Reserved_ = null;
}

再看看mysql吧:com.mysql.jdbc.Driver:
同样发现了static块,里面代码如下:

static {
    try {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
}

再看一个db2:com.ibm.db2.jcc.DB2Driver:
也发现了static块:

static {
    if (o.Nb != null) {
      exceptionsOnLoadDriver__ = dg.a(o.Nb, exceptionsOnLoadDriver__);
    }
 
    try {
      registeredDriver__ = new DB2Driver();
      DriverManager.registerDriver(registeredDriver__);
    }
    catch (SQLException localSQLException) {
      exceptionsOnLoadDriver__ = new SqlException(null,
      "Error occurred while trying to register Jcc driver with JDBC 1 Driver Manager");
      exceptionsOnLoadDriver__.setNextException(localSQLException);
    }
}

无一例外地,发现里面都有DriverManager.registerDriver(driver)的调用。那么是不是可以将开头的例子中的Class.forName换成DriverManager.registerDriver呢?

String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String user = "scott";
String password = "ticmy";
DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
conn.close();

经过测试发现OK。现在,已经知道Class.forName(driver)的根本目的就是为了调用DriverManager.registerDriver

Class.forName还有个重载的方法:Class.forName(String name, boolean initialize, ClassLoader loader),Class.forName(String className)就等价于Class.forName(className, true, currentLoader),注意中间的参数为true,这个参数的含义就是要不要初始化。如果此参数为true且指定的类以前没有被初始化过,就会去初始化。

另外,jdbc4已经不需要显式的调用Class.forName了,在jdbc4中,调用getConnection的时候DriverManager会自动去加载合适的驱动。

分享到:
评论

相关推荐

    JDBC详解HTML-JDBC.pp

    <2>.Class.forName(driver).newInstance() <3>.new driver() 2>.取得数据库连接(Connect to the DataBase) <1>.用DriverManager取数据库连接 Connection cn = DriverManager.getConnection(url,uid,pwd); <2>....

    阿里云java源码-aliyun-odps-jdbc:用于ODPS的JDBC驱动程序

    阿里云java源码数据库接口 中文文档 安装 通常,在您的项目中使用 ODPS JDBC 驱动程序有两种方法。 1.第一个是使用独立库: 从 ...2.二是依靠maven为你解决依赖: ...getConnection(url, accessId, accessKey

    JDBC数据库访问技术全解和实例源代码

    调用Class类forName()方法注册ODBC-JDBC驱动程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 2、建立连接 DriverManager类的getConnection()方法试图定位能连接到数据库的驱动程序 String url="jdbc:...

    eclipse中调用数据库

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); System.out.println("数据库驱动加载成功"); }catch(ClassNotFoundException e){ e.printStackTrace(); } try { String url="jdbc:odbc:Driver={...

    java实验报告:实验六.doc

    发送访问、操作数据库的SQL语句,加载JDBC- ODBC桥驱动程序用class.forName方法来完成 3.处理对数据库访问的结果import java.sql.*; import java.sql.*; import java.util.logging.Level; import java.util.logging....

    jdbc基础和参考

    从Jdk6.0以后要求,JDBC 4.0 Drivers 必须包括 META-INF/services/java.sql.Driver 文件,有了这个文件以后不需要在显示的使用Class.forName来进行驱动的注册 Oracle数据库进行连接的时候,使用的驱动类: 1....

    Java使用表格显示查询结果.rar

      Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); //加载驱动器   Connection con=DriverManager.getConnection(dbURL,user,password); //获取连接   String sqlStr="select * from users"; ...

    JAVA网络通信系统的研究与开发(论文+源代码+开题报告).zip

    当客户端向服务器发送查找好友的请求后,服务器立即响应并调用Class.forname 方法加载数据库驱动类sun.jdbc.odbc.JdbcOdbcDriver , 然后调DriverManager.getConnection完成数据库的连接,得到好友查询的结果。...

    mysql-connector-java-5.1.46-bin

    1.载入驱动 将jar包加入工程,Class.forname(""); 2.建立连接 使用connection对象的getConnection方法   url(jdbc:oracle:thin:@ip:端口:数据库sid),  user,password,如果要手动提交,调用conn.setAutoCommit(false...

    java程序是怎么操作数据库的,可以以常用据库为例,求详细解答,最好能举例。

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //加载jdbc-odbc桥驱动 } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); //加载jdbc-odbc桥错误 System.err....

    数据连接池

    Class.forName(driverClassName).newInstance(); DriverManager.registerDriver(driver); drivers.addElement(driver); log("成功注册JDBC驱动程序" + driverClassName); } catch (Exception e) { log("无法...

    JAVA连接ORACLE数据库方法及测试

    Class.forName(driver); /* 通过DriverManager的getConnection()方法获取数据库连接 */ conn = DriverManager.getConnection(url, user, password); } catch (Exception ex) { System.out.println(...

    数据库连接,里面有各种数据库的连接方法

    Class.forName(driverName); return DriverManager.getConnection(url, user, password); }catch(Exception e){ e.printStackTrace(); return null; } } } DBSQLManager.java //操作数据库用的 ...

    网上购物车 大三实验 今天刚做完

    Class.forName(driver); System.out.println("加载驱动成功"); }catch(ClassNotFoundException e){ System.out.println("加载数据库驱动失败!"); e.printStackTrace(); } } public Connection...

    用java写的MyDB数据库管理器演示程序

    Class.forName("lions.mydb.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mydb://localhost:3305/test", "", ""); Statement stmt = conn.createStatement(); //...

    Excel POI读取封装(文件+示范代码)

    c = st.getConnection(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (rs != null) { rs.close(); } if (st != null) { st.close()...

    (JAVA)BBS论坛设计 内涵代码

    单独写出来并进行编译,也就是数据库连接的javabean文件,编译出来的.class文件是无法被修改的只能通过源文件进行修改,我们在JSP页面中只用直接调用该方法即可,在本系统中我们将其命名为DBConMgr.java 关键代码...

    springmybatis

    <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" /> <property name="username" value="root"/> <property name="password" value="password"/> ...

    二十三种设计模式【PDF版】

    一个设计在最终完成之前常要被复用好几次,而且每一次都有所修改。 有经验的面向对象设计者的确能做出良好的设计,而新手则面对众多选择无从下手,总是求助于以前使用过的非面向对象 技术。新手需要花费较长时间...

    Java连接SQL数据库实现登陆

    Class.forName("com.mysql.jdbc.Driver"); System.out.println("加载驱动成功。"); String url = "jdbc:mysql://localhost/users"; String user = "root"; String password = "123456"; conn = DriverManager....

Global site tag (gtag.js) - Google Analytics