当前位置: 首页 > 知识库问答 >
问题:

为什么Class.for名称似乎没有在驱动程序管理器中注册驱动程序

仲孙宇定
2023-03-14

作为JDBC的新手,我被教导使用Class.forName将驱动程序注册到DriverManager,这似乎不适用于我的代码:

public static void main(String[] args)
{
    System.out.println(DriverManager.drivers().count());

    // clear all loaded drivers
    Iterator<Driver> it = DriverManager.drivers().iterator();

    while (it.hasNext())
    {
        try { DriverManager.deregisterDriver(it.next()); }
        catch (SQLException e) { e.printStackTrace(); }
    }

    System.out.println(DriverManager.drivers().count());

    // register mysql driver with forName
    try { Class.forName("com.mysql.cj.jdbc.Driver"); }
    catch (ClassNotFoundException e) { e.printStackTrace(); }

    System.out.println(DriverManager.drivers().count());

    // register with constructor - works fine
    try { DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); }
    catch (SQLException e) { e.printStackTrace(); }

    System.out.println(DriverManager.drivers().count());
}

每当我编译和运行时,结果总是1,0,0,1。我哪里做错了?

共有2个答案

程赞
2023-03-14

从Java6开始(假设初始类路径上有JDBC 4.0或更高版本的驱动程序),JDBC驱动程序会自动加载。这意味着驱动程序在类加载和初始化的那一刻就会自动加载。

驱动程序类的静态初始化程序是向驱动程序管理器注册驱动程序的程序。加载类时运行此静态初始化程序。由于驱动程序类已经加载,随后的Class.forName返回已经加载的类,并且静态初始化程序不会再次运行,因此没有向driverManager注册任何内容。

换句话说:

  • driverManager是类加载的,并使用ServiceLoader加载驱动程序
    • com.mysql.cj.jdbc.驱动程序通过ServiceLoader加载,其静态初始化器向driverManager
    • 注册一个实例
    • 给定类已被类加载,Java将返回已加载的类
    • 由于静态初始化程序不再运行,因此未注册任何内容

上官高畅
2023-03-14

你说:

我被教导使用Class.for名字

你的老师太落伍了。

在现代Java中,您不再需要调用< code>Class.forName。JDBC驱动程序现在可以通过Java服务提供者接口(SPI)自动加载。如果好奇这是如何工作的,请看这个问题。

如果您的JDBC驱动程序未能自动注册,请验证其是否包含在您的项目中,或者如果在Jakarta EE(JavaEE)服务器中,请验证该环境中的正确位置。您没有发布足够的关于您的开发和部署场景的详细信息,以便我们进行诊断。并验证您是否拥有正确的版本,该版本通常应支持JDBC 4. x(4.3是最新的)。

如果您继续遇到问题,请编写一个一次性控制台应用程序,它除了连接到您的数据库之外什么都不做。尽可能消除复杂性和干扰。

关于您显示的代码,我不知道您为什么要取消注册任何驱动程序。基本上,您在问题中显示的所有代码都应该是不必要的。

此外,通常最好使用DataSource作为连接到数据库的方式。DataSource对象保存连接所需的信息:服务器地址、端口号、用户名、密码和特定于您的数据库服务器产品的各种专有设置。

我写了一些关于堆栈溢出的答案,其中包括MySQL、Postgres、,

这里有一个这样的例子。这里显示的代码应该足够了,因为MySQL驱动程序应该会自动加载。

private DataSource configureDataSource ( )
{
    System.out.println( "INFO - `configureDataSource` method. " + Instant.now() );

    com.mysql.cj.jdbc.MysqlDataSource dataSource = Objects.requireNonNull( new com.mysql.cj.jdbc.MysqlDataSource() );  // Implementation of `DataSource`.
    dataSource.setServerName( "db-mysql-lon2-722-do-user-89973-1.x.db.ondigitalocean.com" );
    dataSource.setPortNumber( 24_090 );
    dataSource.setDatabaseName( "defaultdb" );
    dataSource.setUser( "scott" );
    dataSource.setPassword( "tiger" );
    return dataSource;
}

用法:

Connection conn = myDataSource.getConnection() ;

当然,您应该获得满足您需求的< code>DataSource实现。例如,一些提供全新的连接,而另一些提供连接池。有些是由html" target="_blank">数据库供应商提供的,有些是第三方提供的。

 类似资料:
  • 在Eclipse BIRT数据资源管理器中为查询生成器添加JDBC数据库连接: 选择“查询生成器的JDBC数据库连接” 就这样。我可以使用此数据源来使用数据集。 下一个。 我希望使用更灵活的“JDBC数据源”,而不是以前成功使用的“查询生成器的JDBC数据库连接”。哦,我看到MySQL没有驱动程序类-Derby和Sample只有两个默认条目。 似乎JDBC驱动程序的有效注册没有添加(或注册?)司机

  • 我不知道Spark驱动程序和应用程序主程序之间有什么区别。基本上是在运行一个应用程序中的职责,谁做什么? 在客户端模式下,客户端机器拥有驱动程序,应用程序主程序运行在集群节点中。在集群模式下,客户端没有任何驱动程序,驱动程序和应用程序主程序运行在同一个节点(集群节点之一)。 参考资料: 火花驱动程序内存和应用程序主内存 火花纱集群vs客户端-如何选择使用哪一个?

  • OracleJDBC教程说 在以前版本的JDBC中,要获得连接,首先必须通过调用方法类初始化JDBC驱动程序。forName。这个方法需要一个java类型的对象。sql。驾驶员每个JDBC驱动程序都包含一个或多个实现java接口的类。sql。驾驶员JavaDB的驱动程序是org。阿帕奇。德比。jdbc。嵌入式驱动程序和组织。阿帕奇。德比。jdbc。ClientDriver,MySQL连接器/J的一

  • 搜索上下文是selenium中最超级的接口,它由另一个称为网络驱动程序的接口扩展。 -所有搜索上下文和Web驱动程序接口的抽象方法都在远程WebDriver类中实现。 -所有与浏览器相关的类,如Firefox驱动程序、Chrome驱动程序等,都扩展了远程Webdriver类。 根据上面的stmt,远程web驱动程序类如何为搜索上下文接口和web驱动程序接口中定义的所有抽象方法给出定义。因为功能驱动

  • 问题内容: 之前我曾假设: 平台驱动程序适用于片上设备。 普通设备驱动程序用于与处理器芯片接口的设备。 在遇到一个i2c驱动程序之前…但是在这里,我正在阅读定义为平台驱动程序的多功能i2c驱动程序。我经历了https://www.kernel.org/doc/Documentation/driver- model/platform.txt 。但是对于如何定义驱动程序(如片上和接口设备),仍然没有一

  • 我尝试使用TNS URL、用户名和密码连接到Oracle 11i数据库。JNDI正在成功查找数据源,但我无法获得连接。相反,我看到下面的堆栈跟踪。 我的Maven设置如下。 我的Spring MVC应用程序已经部署到Tomcat 8。我的oracle jar文件位于位置。如下所示 我的web.xml配置 我不确定我做错了什么。我能够使用DriverManager API成功连接。我看了下面的帖子,