为啥是 Class.forName('database driver')?
Posted
技术标签:
【中文标题】为啥是 Class.forName(\'database driver\')?【英文标题】:Why Class.forName('database driver')?为什么是 Class.forName('database driver')? 【发布时间】:2014-07-09 15:05:52 【问题描述】:为什么
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
dbConnection = DriverManager.getConnection(strUrl, props);
而不是
dbConnection = EmbeddedDriver.connect(strUrl, props);
?
指定一个字符串而不是一个可以被编译器检查的类名不是更容易出错吗?我看到了一个示例,其中类名是从配置中获取的,但这似乎是无论可用替代方案如何都使用的模式。
【问题讨论】:
一个可用于动态加载驱动程序,稍后您可以对驱动程序进行硬编码。 实际上现在这两种解决方案都不应该使用。请参阅 Elliott 的回答。 【参考方案1】:使用 JDBC 4.0 驱动程序(及更高版本),您只需要
dbConnection = DriverManager.getConnection(strUrl, props);
根据DriverManager
javadoc,
JDBC 4.0 驱动程序必须包含文件 META-INF/services/java.sql.Driver。此文件包含 java.sql.Driver 的 JDBC 驱动程序实现的名称。例如,要加载 my.sql.Driver 类,META-INF/services/java.sql.Driver 文件将包含以下条目:
my.sql.Driver
应用程序不再需要使用 Class.forName() 显式加载 JDBC 驱动程序。当前使用 Class.forName() 加载 JDBC 驱动程序的现有程序将继续工作而无需修改。
【讨论】:
【参考方案2】:第一个代码 sn-p 让您的程序避免在编译时依赖于 EmbeddedDriver
类。例如,您可以将"org.apache.derby.jdbc.EmbeddedDriver"
字符串放在配置文件中,并在运行时读取它。
第二个代码 sn-p 将对 EmbeddedDriver
类的依赖“烘焙”到程序的主体中,这样就不可能在不重新编译代码的情况下切换驱动程序。
指定一个字符串而不是一个可以被编译器检查的类名不是更容易出错吗?
这绝对是真的。为驱动程序类的名称指定 Java 字符串文字不是正确的方法,因为您的程序不会通过按名称访问类获得任何灵活性。
【讨论】:
但是您实际上需要在运行时从一个驱动程序切换到另一个驱动程序的频率是多少?为什么? @Tiiba 在我处理数据库的许多项目中,程序使用的数据库必须是用户可配置的。同一个程序必须与来自多个供应商的数据库一起工作,而无需重新编译。客户告诉我们他有哪个数据库,我们使用它。客户有自己的理由选择一个 RDBMS 而不是另一个(他们有内部 DBA,他们使用同一供应商的其他产品,等等)。与来自多个供应商的数据库合作的能力为我们带来了竞争优势。 嗯...我想我明白你在说什么了。某种允许用户使用自己的数据库创建应用程序的 Web 托管服务?为了有意义,我给了你 +1 互联网。 (然后我会发现你说得有道理,而我有另一个道理。) @Tiiba Out 产品专为企业部署而设计,客户可以选择数据库的供应商,但随后我们(而不是客户)将创建数据库以供我们的程序使用。客户将维护数据库 - 进行备份、管理其存储、压缩日志等等。【参考方案3】:原因是如果你使用EmbeddedDriver.connect
,那么JVM会在初始化包含该语句的类时加载EmbeddedDriver
类。除此之外,如果在您的类路径中找不到EmbeddedDriver
,这将导致程序失败,即使EmbeddedDriver
类实际上永远不会被使用。 (想要延迟解决课程还有其他原因。)
【讨论】:
【参考方案4】:我认为在 JDBC 的第一个版本中需要确保 DriverManager 在请求连接时加载了驱动程序类。直接访问代码中的驱动程序类需要在编译时驱动程序 JAR 的可用性,这不是 JDBC API 所需的行为。
【讨论】:
以上是关于为啥是 Class.forName('database driver')?的主要内容,如果未能解决你的问题,请参考以下文章
h2 数据库的 ClassNotFound 异常 class.forname("org.h2.Driver")