2

我寻找了一个类似的问题,但只找到了类似的问题,例如Godaddy JNDI 问题---无法为连接 URL 'null' 创建类 '' 的 JDBC 驱动程序,这不能回答我的一般问题。

Tomcat 7.0.8 ..以下代码

Context initialContext = new InitialContext();
datasource = (DataSource) initialContext.lookup("java:comp/env/" + "blah");
Connection c = null;
c = datasource.getConnection();

抛出此错误。

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'
   at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
   at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
   at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
...
Caused by: java.lang.NullPointerException
   at sun.jdbc.odbc.JdbcOdbcDriver.getProtocol(JdbcOdbcDriver.java:527)
   at sun.jdbc.odbc.JdbcOdbcDriver.knownURL(JdbcOdbcDriver.java:496)
   at sun.jdbc.odbc.JdbcOdbcDriver.acceptsURL(JdbcOdbcDriver.java:319)
   at java.sql.DriverManager.getDriver(DriverManager.java:386)
   at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
   ... 24 more

我不是在问它为什么失败或如何修复它。

我的问题是,为什么 LOOKUP 没有失败?

为什么查找创建一个无用的带有空 URL 的 BasicDataSource?有没有比尝试使用它并查看它是否爆炸更好的方法来检测 JNDI 名称是否“不存在”?这种方法让我想起了他们如何测试桥梁

我终于硬着头皮把一堆代码从原始的 JDBC 代码移到了 JNDI,但仍有许多谜团。

如果可能的话,我想避免向下转换 BasicDataSource,以至少保留数据库独立性的错觉。

TIA

4

2 回答 2

4

据我了解 JNDI,它旨在保留对对象 对象工厂的引用。

对象业务很简单——配置器提供对象的引用,应用程序使用它,就这么简单。但是对于更复杂或通用的情况,提供对对象工厂的引用会更方便,这为如何创建对象提供了更多的自由。

由于您尚未发布您的 webappweb.xml和 Tomcat conf/server.xml,因此很难详细说明,但我猜您的 web.xml 中有类似的内容

<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/myDB</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

如果您阅读Tomcat 的 JNDI howto,您应该会看到:

如果 Tomcat 能够识别合适的资源工厂来创建资源,并且不需要进一步的配置信息,Tomcat 将使用 /WEB-INF/web.xml 中的信息来创建资源。

现在,让我们看看Tomcat 对上述. 在第 112 行,您可以看到如果给定res-type等于javax.sql.DataSource,则它用于org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory创建新的数据源。

就是这样。至此,JNDI 的工作就结束了,因为它对对象的创建方式没有任何影响——这是理所当然的!不要忘记 JNDI 旨在存储对任何类型对象(邮件连接、安全领域等)的引用。为每种不同类型的对象编写测试既不可能也不合理。即便如此,仅仅通过数据库设置,也无法确定这些设置是否足以建立与真实数据库的实时连接。

这就是为什么你有一个单独的电话,datasource.getConnection()这就是为什么它会抛出SQLException你应该捕捉和处理的东西。

ps你可能会争辩说BasicDataSourceFactory应该更聪明,并且有一个强制性属性/参数列表。也许。但这是另一个问题的主题,因为最初你问为什么 LOOKUP 没有失败 ;)

于 2011-02-26T21:27:22.250 回答
1

在 tomcat 上运行 war 文件时,web.xml 和 server.xml 将一起为您提供此处描述的定义。有时,在 Eclipse 中,您使用的 web.xml 可能与您想象的不同。确保 Eclipse 中的调试器正在加载您期望的 web 和 server.xml 文件。我发现在我的情况下 web.xml 没有定义,所以在那里添加它并且这有效。

于 2014-03-25T12:54:41.483 回答