为什么我们在连接数据库时使用Class.forName(“oracle.jdbc.driver.OracleDriver”)?

连接数据库时Class.forName("oracle.jdbc.driver.OracleDriver")的实际用途是什么? 为什么我们不能导入相同的类,而是我们为什么要加载它。

使用Class.forName()的基本思想是加载JDBC驱动程序实现。 (普通)JDBC驱动程序必须包含一个静态初始化程序,它使用java.sql.DriverManager注册驱动程序实现的实例:

JDBC驱动程序必须实现Driver接口,并且实现必须包含将在加载驱动程序时调用的静态初始化程序。 此初始化程序使用DriverManager注册其自身的新实例

(来自JDBC 4.1,第9.2节)

但是从JDBC 4.0开始,有一种注册驱动程序的新方法:JDBC驱动程序的jar需要包含一个文件/META-INF/services/java.sql.Driver ,它包含java.sql.Driver的名称那个jar子里的实现。 使用DriverManager创建连接时,它将使用java.util.ServiceLoader枚举类路径中的所有/META-INF/services/java.sql.Driver文件,并加载所有驱动程序以便注册。

DriverManager.getConnection方法已得到增强,可支持Java Standard Edition Service Provider机制。 JDBC 4.0驱动程序必须包含文件META-INF/services/java.sql.Driver 。 此文件包含JDBC驱动程序的java.sql.Driver实现的名称。

(来自JDBC 4.1,第9.2.1节)

驱动程序以这种方式加载的原因是它允许您将应用程序与它使用的驱动程序(和数据库)分离。 这意味着您可以编写,编译甚至分发没有任何驱动程序的应用程序,您只需要使用java.sql (和javax.sql )包中提供的接口 – 这是Java的一部分 – 无需访问实现直。

然后,应用程序的用户将有效的JDBC驱动程序添加到类路径中(并配置连接字符串之类的内容),以便应用程序实际上可以连接到数据库。 在JDBC 4.0之前,用户必须指定驱动程序名称,以便应用程序可以使用Class.forName加载它,使用JDBC 4.0兼容驱动程序和Java 6或更高版本,此发现是自动的。

当您使用Class.forName("oracle.jdbc.driver.OracleDriver")逐字加载驱动程序时,它可能感觉有点过分,但如果您记住它也可能是从配置文件(或从用户输入)拉出的字符串你可能会开始明白为什么它如此强大。

当然,这种驱动程序独立性不是100%,尤其是如果您的应用程序使用特定于供应商的SQL。 但理论是您的应用程序可以独立于数据库。 JDBC还提供了一些额外的机制来解决这个问题,例如JDBC转义提供驱动程序转换为特定语法的通用语法, DatabaseMetaData允许您发现允许您创建或生成兼容查询的function,保留字等。

有几个理由使用Class.forName("")而不是直接引用该类:

  1. 使用Class.forName("")可以更明显地控制在代码中第一次尝试加载指定类的确切位置。 如果代码运行时类代码中不存在该类,则代码将失败(抛出exception)的位置更加明显。

  2. 如果您只是导入类然后在代码中引用它,那么如果该类不存在,代码将抛出exception会变得稍微不那么明显。

  3. 此外,使用Class.forName("")是一种解决潜在编译时限制的方法。 例如,如果编译代码的人没有(因为,许可或知识产权原因)可以访问类oracle.jdbc.driver.OracleDriver,他们可能会发现编译引用该类的代码更容易Class.forName("")而不是直接。

  4. 如果您不需要使用指定类的任何方法,字段或内部类,那么Class.forName("")可能是最明确的方式来表示唯一需要的是加载类(并具有静态)初始化程序运行),没有别的。

我不认为Class.forName表现出任何不同于直接引用类的function行为。 它默认使用调用类’classloader,它应该是直接引用类时使用的相同类加载器。 Class.forName(“”)有一些重载可以让你自定义类加载行为。

这是一种传统的方式。 导入类将具有额外的依赖性

来自Java教程:

在以前的JDBC版本中,要获得连接,首先必须通过调用Class.forName方法来初始化JDBC驱动程序。 此方法需要java.sql.Driver类型的对象。 每个JDBC驱动程序都包含一个或多个实现接口java.sql.Driver的类。

在类路径中找到的任何JDBC 4.0驱动程序都会自动加载。 (但是,必须使用方法Class.forName手动加载JDBC 4.0之前的任何驱动程序。)

Class.forName(“oracle.jdbc.driver.OracleDriver”)将类名作为字符串参数并将其加载到内存中。 加载类的第二种方法是使用new创建它的实例。 第二种方法的缺点是如果你不需要它,新创建的实例将毫无用处。

有一个很好的教程解释了JDBC连接基础知识 。

有时需要在运行时加载一个类。 即,在执行java应用程序时,可以动态地将任何类加载到内存位置。 Class.forName用于在运行时加载任何给定的类(在双引号内作为String)。 例如,当我们使用IDE时,我们会看到将有一个GUI构建器,它允许我们拖放按钮,文本字段等。这种拖放机制在内部需要在运行时加载某些类。

在Class.forName( sun.jdbc.odbc.JdbcOdbcDriver )中,Class属于java.lang.Class包,而forName()java.lang.Class的静态方法。 JDBC驱动程序(String)将在运行时动态加载到类中,forName方法包含静态块,该块创建Driver类对象并自动向DriverManager服务注册。 由于forName()是静态的,我们使用类名(Class)来调用它。

让我们理解静态和动态类加载的概念

静态类加载:使用new关键字创建对象称为静态类加载。

动态类加载:加载类使用Class.forName()方法。

因此,当我们使用动态类加载时,它允许传递类名,因此用户可以轻松地在DB供应商之间切换(需要处理数据库引擎的特定代码)

当我们想要执行类的静态块而不创建它的对象时,我们可以使用class.forName()Driver类所做的大部分工作都存在于静态块中。

现在我们在JDBC连接中需要的是使用DriverManager注册驱动程序并获取与它的连接,因此只需通过执行静态块并且不需要创建该类的对象即可实现。 这种方法将提供更好的性能。

这用于打开一个类,或者换句话说,通过其名称从字符串格式调用它。
例如:

 Class.forName("com.android.example.MainClass"); 

它将在com / android / example / MainClass.java包中启动类