作为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。我哪里错了?
JDBC驱动程序在现代Java中自动注册
你说:
我被教导使用Class.forName
你的老师已经过时了。
在现代Java中,您不再需要调用Class.forName
。JDBC驱动程序现在通过Java服务提供程序接口(SPI(自动加载。如果想知道这是如何工作的,请参阅此问题。
如果JDBC驱动程序未能自动注册,请验证它是否包含在项目中,或者如果在Jakarta EE(Java EE(服务器中,请验证该环境中的正确位置。您没有发布足够的关于您的开发和部署场景的详细信息供我们诊断。并验证您是否拥有正确的版本,该版本通常应该支持JDBC 4.x(4.3是最新版本(。
如果您仍然有问题,请编写一个一次性控制台应用程序,该应用程序除了连接到您的数据库之外,什么都不做。尽可能多地消除复杂性和干扰。
关于你显示的代码,我不知道你为什么要注销任何司机。基本上,你在问题中显示的所有代码都应该是不必要的。
DataSource
此外,通常最好使用DataSource
作为连接数据库的方式。DataSource
对象包含连接所需的信息:服务器地址、端口号、用户名、密码以及特定于数据库服务器产品的各种专有设置。
我已经写了一些关于堆栈溢出的答案,并为MySQL、Postgres和&H2。就像这个。我建议你从我和Stack Overflow上的许多其他优秀作者那里搜索这样的例子。
这里有一个这样的例子。这里显示的代码应该足够了,因为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() ;
当然,您应该获得满足您需求的DataSource
实现。例如,一些提供新的连接,而另一些提供连接池。有些是由数据库的供应商提供的,有些是第三方的。
由于Java 6(假设初始类路径上有JDBC 4.0或更高版本的驱动程序(,JDBC驱动程序会自动加载。这意味着驱动程序在DriverManager
被类加载和初始化时自动加载。
驱动程序类的静态初始值设定项向驱动程序管理器注册驱动程序。该静态初始值设定项在加载类时运行。由于驱动程序类已经加载,随后的Class.forName
返回已经加载的类,并且静态初始值设定项不会再次运行,因此不会向DriverManager
注册任何内容。
换句话说:
DriverManager
是类加载的,并使用ServiceLoader
加载驱动程序com.mysql.cj.jdbc.Driver
通过ServiceLoader
加载,其静态初始值设定项向DriverManager
注册一个实例
- 您从
DriverManager
中删除所有驱动程序 - 您拨打
Class.forName("com.mysql.cj.jdbc.Driver")
- 给定类已经加载,Java返回已经加载的类
- 由于静态初始化程序不再运行,因此未注册任何内容
- 您可以手动向
DriverManager
注册一个实例(顺便说一句,这不是您通常应该做的事情,DriverManager.registerDriver
是供JDBC驱动程序调用的(