为什么在使用JDK 8时需要显式编写Class.forName()? [英] Why do I need to explicitly write Class.forName() when using JDK 8?

查看:91
本文介绍了为什么在使用JDK 8时需要显式编写Class.forName()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在stackoverflow中看到了很多答案,说

在Java 6之前的版本中,DriverManager类不会知道您要使用哪个JDBC驱动程序. Class.forName("...")是预加载驱动程序类的一种方法. 如果您使用的是Java 6,则不再需要这样做.

我正在为我的Web应用程序使用Oracle12c数据库和JDK 8,以及最新版本的eclipse和tomcat.此外,还添加了最新的ojdbc7.jar和servlet-api.jar来构建路径.

这是我的servlet代码:

public class NewServlet extends HttpServlet {
private static final long serialVersionUID = 102831973239L  ;

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        Connection con;
        try {
            con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","system","kiran12c");
            Statement stmt = con.createStatement();
            stmt.executeQuery("create table SpinCart_Customers1(cid number,cname varchar2(20))");
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

}

但是当我运行在数据库中创建表的servlet时,在控制台中出现以下错误:

java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@localhost:1521:orcl

如果我添加以下代码,它就可以正常工作(表已成功创建).

try{
    Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(java.lang.ClassNotFoundException e)
{
    e.printStackTrace();
}

为什么会这样?我正在使用jdk8,为什么还需要使用Class.forname()?

解决方案

Class.forName("X")实际上做一件事:它告诉类加载器在类路径中搜索类X并尝试加载它.副作用是,类中的任何静态初始化器都有运行的机会.仅当JVM首次遇到类X时,才会发生这种情况.当您的一个类将类X引用为导入时,也会发生相同的事情,但在Class.forName("X")X中不必在编译时出现. /p>

JDBC供应商通常使用静态初始化程序在JDBC驱动程序管理器中注册其驱动程序.没有它,DriverManager不会知道提供程序可用,并且无法返回连接. (在大多数情况下,您仍然可以绕过DriverManager并直接使用完全合格的供应商类,但这会将您的代码耦合到特定的供应商.)使用Class.forName()注册驱动程序是特定于供应商的,并且不受JDBC的严格要求.无论如何,您都应遵循供应商的说明,因为只有他们才能告诉您应该如何使用其驱动程序.

I have seen a lot of answers in stackoverflow say that

Pre Java 6 the DriverManager class wouldn't have known which JDBC driver you wanted to use. Class.forName("...") was a way on pre-loading the driver classes. If you are using Java 6 you no longer need to do this.

I am using Oracle12c database and JDK 8 with latest version of eclipse and tomcat for my web application. Also latest ojdbc7.jar and servlet-api.jar are added to build path.

Here's my servlet code:

public class NewServlet extends HttpServlet {
private static final long serialVersionUID = 102831973239L  ;

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        Connection con;
        try {
            con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","system","kiran12c");
            Statement stmt = con.createStatement();
            stmt.executeQuery("create table SpinCart_Customers1(cid number,cname varchar2(20))");
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

}

But when I run my servlet which creates a table in my database, I am getting the following error in console:

java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@localhost:1521:orcl

If I add the following code it is working fine (table successfully created).

try{
    Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(java.lang.ClassNotFoundException e)
{
    e.printStackTrace();
}

Why is this happening? I am using jdk8, why do I still need to use Class.forname()?

解决方案

Class.forName("X") actually does one thing: it tells the classloader to search the classpath for class X and try to load it. As a side effect, any static initializers in class get their chance to run. This happens only when JVM first encounters class X. The same thing happens when one of your classes references class X as an import, except that in Class.forName("X") X does not have to be present at compile-time.

JDBC vendors typically use static initializers to register their driver with JDBC driver manager. Without it, DriverManager is not aware that provider is available, and cannot return a Connection. (In most cases, you can still bypass DriverManager and use fully qualified vendor classes directly, but that couples your code to specific vendor.) Registering a driver with Class.forName() is vendor-specific and not strictly mandated by JDBC. In any case, you should follow the vendor's instructions, because only they can tell you how their driver is supposed to be used.

这篇关于为什么在使用JDK 8时需要显式编写Class.forName()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆