Oracle数据库连接未找到合适的驱动程序。

14

我有一个小的Java应用程序,每天使用Cronj调度程序检查数据库中的数据,并且一切都运行良好。但最近我发现,它由于某些原因失败了。

java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@160.110.xx.xxx:1521/test

同时,当我运行我的测试代码以检查数据库连接性时,它可以正常工作,没有出现上述异常。我无法找出原因。尽管只有轻微的代码更改,但与数据库或数据库连接无关。请问,有人可以帮助我吗?

dbconf.java

public class dbconf {

    private Connection connect;
    private String connstr;

    public Connection getConnection() throws SQLException {
        connstr = "jdbc:oracle:thin:@160.110.xx.xxx:1521/test";

        try {
                String uname = "scott";
                String pass = "tiger";
                Class.forName("oracle.jdbc.OracleDriver").newInstance();
                connect = DriverManager.getConnection(connstr, uname, pass);

        } catch (Exception e) {
            System.out.println(e.toString());
        }

            return connect;
    }
}

我正在使用 ojdbc6.jarOracle11g

已编辑 - 应用程序日志文件

Wed Jul 01 09:25:17 IST 2015:------- Initializing -------------------
Wed Jul 01 09:25:17 IST 2015:------- Scheduling Jobs ----------------
Wed Jul 01 09:25:17 IST 2015:------- Job Started Running ----------------
Thu Jul 02 06:00:00 IST 2015 : Job Executed..!! Bschedularv2.2
java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@160.xxx.67.xxx:1521/test
Sat Jul 04 06:00:00 IST 2015 : Job Executed..!! Bschedularv2.2
Sun Jul 05 06:00:00 IST 2015 : Job Executed..!! Bschedularv2.2
java.sql.SQLException: No suitable driver found for jdbc:oracle:thin:@160.xxx.67.xxx:1521/test

因此,您可以看到,它在7月3日和7月6日失败了。但是,在此期间它运行正常。

==更新1==

似乎没有人仔细阅读我的问题,我已经清楚地说明了,它有时运行良好,有时会失败。如果这是类路径问题,那么它不应该每天都运行。

===更新2===

下面的许多答案都是无意义的,但有些具有一定的逻辑观点。我使用了printStackTrace并尝试调试每个点,最后我得到了一些线索。3天前,我在同一台服务器上部署了新版本的应用程序(包括printStackTrace和SysOut),前两天它运行正常,今天出现了以下错误。

INFO: Illegal access: this web application instance has been stopped already.  Could not load com.schedular.job.BirthdayJob.  The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    at org.quartz.simpl.LoadingLoaderClassLoadHelper.loadClass(LoadingLoaderClassLoadHelper.java:59)
    at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:99)
    at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:138)
    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2816)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2759)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2757)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3787)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2756)
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:272)

Jul 13, 2015 6:00:00 AM org.apache.catalina.loader.WebappClassLoader loadClass
INFO: Illegal access: this web application instance has been stopped already.  Could not load com.schedular.job.BirthdayJob.  The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
    at org.quartz.simpl.LoadingLoaderClassLoadHelper.loadClass(LoadingLoaderClassLoadHelper.java:59)
    at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:99)
    at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:138)
    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1385)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggerFired(JobStoreSupport.java:2964)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$43.execute(JobStoreSupport.java:2908)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$43.execute(JobStoreSupport.java:2901)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3787)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggersFired(JobStoreSupport.java:2900)
    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:336)

那是我们的假设。但是,它不起作用。甚至我都没有任何线索来追踪它。 :( - Ravi
问题:上面代码中显示的方法... dbconf.java ...是静态的吗?建议:Class.forName("oracle.jdbc.OracleDriver").newInstance(),这里不需要newInstance()。为什么要使用它? - Pranav Maniar
@PranavManiar 这有什么区别吗? - Ravi
静态方法可能会产生影响,如果没有正确同步,会抛出错误,在代码中很难找到。 - Pranav Maniar
@PranavManiar,请查看我的更新。我在你编辑的评论上回复了。我说,当你说你不应该使用newInstance()方法时,这是否重要。 - Ravi
显示剩余10条评论
12个回答

1

不确定是否有帮助,但这是我用来做同样事情的代码,

    try { 
        Class.forName("oracle.jdbc.driver.OracleDriver"); 
    } catch (ClassNotFoundException e) { 
        System.out.println("Could not load the driver"); 
    } 

    Connection conn = DriverManager.getConnection                                     ("jdbc:oracle:thin:@ten10:1521:acdb", user, pass); 

因此,Class.forName并不完全相同,但协议形式相同。

类的名称很重要,它确保类加载器已加载Oracle jdbc驱动程序。

可能发生的情况是在运行代码的计算机上存在某些连接问题,因此包含实际ojdbc6.jar文件的位置(如类路径所指向的位置)并不总是可访问的(如果它不在本地磁盘上?)。


0

当它说找不到类时,它确实找不到这个类。

根据我的经验,有时起作用,有时无法工作的此类问题与线程有关。 我的假设是 ClassLoader 异步加载您的类,因此在加载后立即调用连接可能是问题所在。 您是否尝试在静态部分中加载Oracle类? 类似于:

public class dbconf {

static {
  Class.forName("oracle.jdbc.OracleDriver");
}

public Connection getConnection() throws SQLException {
    String connstr = "jdbc:oracle:thin:@160.110.xx.xxx:1521/test";
    try {
        String uname = "scott";
        String pass = "tiger";
        return DriverManager.getConnection(connstr, uname, pass);
    } catch (Exception e) {
        System.out.println(e.toString());
    }
}
}

另一个问题是:您的代码每天是否被编译(通过持续交付或其他方式)?

不是的。它只被编译了一次,然后部署到服务器上。你说得很有道理。 - Ravi

0
如果可能的话,请查看DriverManager.getConnection()方法的println。在失败时,您可能会从DB获取一个空连接对象而没有任何异常。
SQLException reason = null;
for(DriverInfo aDriver : registeredDrivers) {
    if(isDriverAllowed(aDriver.driver, callerCL)) {
        try {
            println("    trying " + aDriver.driver.getClass().getName());
            Connection con = aDriver.driver.connect(url, info);
            if (con != null) {
                println("getConnection returning " + aDriver.driver.getClass().getName());
                return (con);
            }
        } catch (SQLException ex) {
            if (reason == null) {
                reason = ex;
            }
        }

    } else {
        println("    skipping: " + aDriver.getClass().getName());
    }

}
if (reason != null)    {
    println("getConnection failed: " + reason);
    throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");

0
不要以静态方式保留驱动程序名称。使用JDBC + Java API获取驱动程序类名,如下所示:
public class dbconf {

    private Connection connect;
    private String connstr;

    public Connection getConnection() throws SQLException {
        connstr = "jdbc:oracle:thin:@160.110.xx.xxx:1521/test";

        try {
                String uname = "scott";
                String pass = "tiger";
                Class.forName(OracleDriver.class.getClass().getName().toString()).newInstance();
                connect = DriverManager.getConnection(connstr, uname, pass);

        } catch (Exception e) {
            System.out.println(e.toString());
        }

            return connect;
    }
}

如果您输入了任何错别字,您可以检查ojdbc6.jar是否已经正确设置在构建路径中,这样会更好。

希望这些信息能够帮到您...


0
一个可能的解决方案是:进入事件查看器 -> Windows 存档,删除应用程序事件和系统事件(不要删除安全事件!)。之后重新启动您的电脑,问题就会解决。

这是服务器。我已经提到了它。我没有重启它的特权。 - Ravi

0

我不熟悉“schedular”,但您最新的更新表明,您有一些线程没有从以前的未部署/重新部署中干净地停止。JavaSpecialists newsletter about how to shutdown threads cleanly 有关如何清理关闭线程的内容。

我想知道您的servlet关闭代码是否注销了数据库驱动程序?从您的堆栈跟踪中看,您正在运行Tomcat。即使您的代码没有直接注销驱动程序,我相信Tomcat 7及以上版本将注销驱动程序作为Tomcat内存泄漏检测/缓解的一部分。

这可能解释了为什么驱动程序有时存在,有时不存在。


0

有人向我寻求解决此问题的方案,现在我将其发布。

  1. 我取消部署了出现此问题的应用程序,并从服务器清理了所有相关文件。
  2. 然后,我重新启动了Tomcat服务器。这样,它将刷新所有临时文件和缓存。
  3. 然后,我部署了相同的应用程序,它开始正常工作,没有任何问题。

0

您的JDBC URL格式不正确,与您所写的不同:

connstr = "jdbc:oracle:thin:@160.110.xx.xxx:1521/test";

应该是以下两种格式之一:

connstr = "jdbc:oracle:thin:@//160.110.xx.xxx:1521/test";

或者

connstr = "jdbc:oracle:thin:@160.110.xx.xxx:1521:test";

具体取决于'test'是服务还是SID。

您展示的日志片段并没有显示第四次调用getConnection方法成功!它只是表明没有抛出错误。这可能意味着该方法从未被调用(因此没有尝试连接)。


那么,第二个和第三个发生了什么?代码没有改变。同样的方法每天以相同的方式被调用。 - Ravi

0

看起来,你的应用服务器的CLASSPATH中没有"ojdbc6.jar"。


那么为什么它运行了几天呢?它不应该一直运行的,对吧?这根本不是逻辑上合理的答案。 - Ravi

0

看起来问题出在你的jar文件上,请尝试替换为ojdbc14.jar并将其添加到类路径中。如果你正在使用Eclipse,请按照以下步骤操作: Eclipse -->(选择项目)转到属性 --> Java Build Path --> 选择添加Jar或添加外部Jar。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接