找不到适合的驱动程序以连接到jdbc:postgresql://192.168.1.8:5432/NexentaSearch。

13

我写了下面这个Java程序

import java.io.*;
import java.util.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.*;

public class Sample {
    public static void main (String[] args) throws IOException  {
                    int CountComputers;
            FileInputStream fstream = new FileInputStream(
                    "/export/hadoop-1.0.1/bin/countcomputers.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
            String result=br.readLine();
            CountComputers=Integer.parseInt(result);
            input.close();
            fstream.close();
            Connection con = null;
            Statement st = null;
                ResultSet rs = null;    
               String url = "jdbc:postgresql://192.168.1.8:5432/NexentaSearch";
                String user = "postgres";
                String password = "valter89";
            ArrayList<String> paths = new ArrayList<String>();
            try
            {
                con = DriverManager.getConnection(url, user, password);
                        st = con.createStatement();
                        rs = st.executeQuery("select path from tasks order by id");
                while (rs.next()) { paths.add(rs.getString(1)); };
                PrintWriter zzz = null;
                    try
                    {
                            zzz = new PrintWriter(new FileOutputStream("/export/hadoop-1.0.1/bin/readwaysfromdatabase.txt"));
                    }
                    catch(FileNotFoundException e)
                    {
                            System.out.println("Error");
                            System.exit(0);
                    }
                    for (int i=0; i<paths.size(); i++)
                {
                    zzz.println("paths[i]=" + paths.get(i) + "\n");
                    }
                    zzz.close();

            }
            catch (SQLException e) 
            {
                System.out.println("Connection Failed! Check output console");
                e.printStackTrace();
            }
        }
}

我编译了这个程序并创建了jar文件

./javac -classpath /folder/postgresql-8.4-703.jdbc3.jar -d /Samplejavaprogram/classes /Samplejavaprogram/src/Sample.java
./jar -cvf /Samplejavaprogram/Sample.jar -C /Samplejavaprogram/classes/ .

Jar文件包含以下清单文件:

Manifest-Version: 1.0
Created-By: 1.7.0_06 (Oracle Corporation)
Main-Class: Sample
Class-Path: /folder/postgresql-8.4-703.jdbc3.jar

还包含文件/folder/postgresql-8.4-703.jdbc3.jar。我通过命令启动了Sample.jar

./java -jar -Djava.library.path=/opt/jdk1.7.0_06/lib /Samplejavaprogram/Sample.jar

因此我收到了以下信息:

Connection Failed! Check output console
java.sql.SQLException: No suitable driver found for jdbc:postgresql://192.168.1.8:5432/NexentaSearch
    at java.sql.DriverManager.getConnection(DriverManager.java:604)
    at java.sql.DriverManager.getConnection(DriverManager.java:221)
    at org.myorg.Sample.main(Sample.java:33)

我从地址为192.168.1.10的主机上启动了文件,在地址为192.168.1.8的主机上它正常运行。请帮助消除一个错误。


哪一行抛出了异常? - Evans
你能给我展示一下你的JAR文件吗? - Sark
请勿使用DataInputStream读取文本,也请从您的示例中删除它。这是一个经常被复制的坏主意。http://vanillajava.blogspot.co.uk/2012/08/java-memes-which-refuse-to-die.html - Peter Lawrey
3个回答

19

您正在使用JDBC 3驱动程序。JDBC 4驱动程序由DriverManager自动加载,而JDBC 3驱动程序则不是。因此,您需要调用

Class.forName("org.postgresql.Driver");

在调用DriverManager#getConnection之前,在您的应用程序中执行此操作。


另外,您可以使用来自此处的JDBC 4 PostgreSQL驱动程序,它不需要上述方法调用。


1
我在Tomcat8上使用JDBC 4时也遇到了这个问题。 - Shoham

0
只需使用jar命令提取应用程序所需的文件,以便与数据库服务器建立连接。例如,jar -xf jdbc_file。使用javac -cp .进行编译,并使用java -cp .运行它。
就是这样。它会正常工作。

0

使用DriverManager.registerDriver(new org.postgresql.Driver());



DriverManager.registerDriver 方法通常应该只由 JDBC 驱动程序调用(当类被加载时它们会这样做)。应用程序代码不应该调用它(有一些例外情况,但这些情况极为罕见)。 - Mark Rotteveel
@MarkRotteveel 感谢您的评论。但是,您不能仅仅说某些东西不应该被使用而不提供任何原因或细节。至少提供一个链接到相关文档会很有帮助。 - pedram bashiri
来自DriverManager.registerDriver的Java文档引用:“新加载的驱动程序类应调用registerDriver方法,以使自己为DriverManager所知。”这意味着它通常应该由Driver实现调用。而java.sql.Driver则表示:“当加载Driver类时,应创建一个自身的实例并将其注册到DriverManager中。” - Mark Rotteveel
我建议阅读JDBC 4.3规范,第9.2节描述了驱动程序如何注册自己以及如何加载驱动程序。所有这些都清楚地表明该方法不适用于用户代码调用。 - Mark Rotteveel
谢谢,这很有帮助。我建议这个解决方案的原因是,据我所记,"Class.forName(something)" 对我没有起作用,经过一些搜索,我找到了 "https://docs.oracle.com/cd/F49540_01/DOC/java.815/a64685/basic1.htm" 这个非常古老的文档,但我还是尝试了一下,结果它起作用了。但现在,通过您发布的链接,我同意,这不应该被使用。 - pedram bashiri
1
Oracle文档描述的内容可以运行,但这不是JDBC驱动程序的预期使用方式。他们可能会记录下来,因为有关Class.forName的注释:“但是,此方法仅适用于符合JDK的Java虚拟机。它不适用于Microsoft Java虚拟机。”,这似乎将其日期限制在90年代末、2000年代初,当时Microsoft拥有自己的Java变体,并且并非始终兼容。 - Mark Rotteveel

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