【问题标题】:What is the purpose of 'Class.forName("MY_JDBC_DRIVER")'?'Class.forName("MY_JDBC_DRIVER")' 的目的是什么?
【发布时间】:2011-12-01 13:13:28
【问题描述】:

我知道类加载对于在运行时使用类名加载类很有用。

但是,在我们的项目中使用 JDBC 时,我们知道要使用哪个驱动程序,并且大多数驱动程序管理器字符串是硬编码的。

我的问题是:为什么我们在这里使用Class.forName("JDBC_DRIVER") 加载驱动程序?
为什么我们不能继续在类路径中添加驱动程序?因为我们知道要使用哪个驱动程序 jar。

我相信Class.forName(JDBC_DRIVER) 会将驱动程序加载到DriverManager。这是唯一的原因吗?

编辑 1:

DriverManager API doc 声明

作为其 (DriverManager) 初始化的一部分,DriverManager 类将尝试加载“jdbc.drivers”系统属性中引用的驱动程序类。

应用程序不再需要使用Class.forName() 显式加载 JDBC 驱动程序。当前使用 Class.forName() 加载 JDBC 驱动程序的现有程序将继续工作而无需修改。

然后当我使用非 oracle 驱动程序时;我需要更改系统属性中的驱动程序名称字符串吗?

【问题讨论】:

  • 组,谢谢。现在我明白了 class.forName() 与其他机制(例如调用其静态方法或创建该类的实例)相比,对于加载类很有用。这样我们可以确保在加载时使用静态块只执行一次某些功能。

标签: java jdbc


【解决方案1】:

首先:使用现代 JDBC 驱动程序和当前的 JDK(至少 Java 6)不再需要调用 Class.forName()JDBC driver classes are now located 使用 service provider mechanism。您应该能够简单地删除该调用并保持其余代码不变,它应该可以继续工作。

如果您没有使用当前的 JDK(或者如果您的 JDBC 驱动程序没有设置了适当的文件来使用该机制),那么驱动程序需要注册到DriverManager 使用 registerDriver。该方法通常从实际驱动程序类的静态初始化程序块调用,该程序在第一次加载类时触发,因此发出 Class.forName() 可确保驱动程序自行注册(如果不是t 已经完成了)。

无论您使用Class.forName() 还是新的服务提供者机制,您将始终需要类路径上的 JDBC 驱动程序(或者至少在运行时通过一些 ClassLoader 提供) .

tl;dr:是的,Class.forName() 调用的唯一用途是确保驱动程序已注册。如果您使用当前的 JDK 和当前的 JDBC 驱动程序,则不再需要此调用。

【讨论】:

  • 是的!在没有 Class.forName() 行的 java6 中; DriverManager 能够为 oracle 驱动程序创建连接。我刚测试过。它是通过 loadInitialDrivers() :: DriverManager 完成的。谢谢!
  • @Joachim,JustinK 的评论 stackoverflow.com/questions/8053095/… 指出,对于 JDBC 4 之前的版本,Class.forName仅在驱动程序不在类路径上时才需要。为什么 JustinK 的评论与您所说的我们“将始终需要类路径上的 JDBC 驱动程序”的引用直接矛盾?
  • @Pacerier:JustinK 正在讨论在构建代码时 将驱动程序放在类路径中。除非您以某种方式直接访问驱动程序类(您可能需要它访问一些非标准功能,否则这不太可能),否则这绝不是必要的。在运行时,无论您如何访问它,您都需要将驱动程序放在类路径上(或者如果您愿意,也可以在自定义类加载器上,但这几乎是一样的东西),否则无法加载。跨度>
  • @JoachimSauer,确实如此,是的,因为自定义类加载器被广泛使用,你的声明“你总是需要类路径上的 JDBC 驱动程序”应该被编辑。这是错误的,因为我们根本不需要类路径上的驱动程序,因为使用类加载器,我们可以通过文件/内存/网络/用户输入加载 JDBC 驱动程序。 (顺便说一句,为迟到的回复道歉,“:”字符似乎不适用于“@”)
【解决方案2】:

Class.forName(JDBC_DRIVER)调用会在DriverManager中注册你的JDBC驱动,所以你可以通过url来寻址,比如“jdbc:odbc:Database”等等……

通常驱动类有这样的静态初始化代码,在 Class.forName() 上调用:

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

您仍然需要将 JDBC 驱动程序 jar 放入类路径中。

作为替代方案,您可以使用特定于数据库的 DataSource,然后您可以以声明方式指定数据源类型,例如在 Spring 上下文中或在您的 Web 服务器 JNDI 中。这是example

【讨论】:

  • 从技术上讲,这是在加载类时调用的,不一定是在 Class.forName() 上,这只是强制加载卸载的类的一种方法。
【解决方案3】:

将类放在类路径中不足以让类加载器加载它。并且必须加载驱动程序类以确保它已注册到 JDBC API。顺便说一句,要使Class.forName 工作,驱动程序类必须在类路径中。

【讨论】:

    【解决方案4】:

    在许多工业应用中,我们希望通过以属性文件/配置文件的形式提取此类信息,从而从其余代码中抽象出数据访问层。在这些情况下,我们可能需要像您一样使用某些东西。

    例如我们可以使用 JDBC 接口类编写代码来访问数据库,您可以通过选择要用作数据库的技术(例如 ojdbc 驱动程序或 mysql jdbc 驱动程序等)来配置属性。在这些情况下,您可以使用这种方法加载类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-08
      • 2011-01-06
      • 2013-02-08
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      • 2011-12-24
      相关资源
      最近更新 更多