需要帮助通过Java进程执行Postgresql查询

时间:2018-12-05 14:27:09

标签: java

我需要执行一个bat文件,该文件在Windows 10和Java-8中使用psql.exe在命令行中执行PostgreSQL查询。我必须通过bat文件执行查询,仅用于测试bat文件。下面是蝙蝠文件的内容

BatFileContents:

postgresql\bin\psql.exe -U username -p dbport -h 127.0.0.1 -c "
insert into table1 values(value1,value2);
insert into table2 values(value1,value2);
insert into table3 values(value1,value2) database"

我尝试使用java ProcessBuilder调用bat文件,但是pgsql要求输入密码。下面是我用来调用bat文件并提供密码的代码,但是它无法正常工作。

代码:

主类:

import java.io.BufferedWriter;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class ProcessTest {


    public static void main(String args[])
    {

        Process process=null;

        String batFile="\"c:\\batfilepath\\test.bat\"";

        ProcessBuilder processBuilder=new ProcessBuilder(batFile);

        try {

            //process=Runtime.getRuntime().exec(batFile);

            process=processBuilder.start();

            StreamEater inputStreamEater=new StreamEater(process.getInputStream());

            StreamEater errorStreamEater=new StreamEater(process.getErrorStream());

            inputStreamEater.start();

            errorStreamEater.start();

            BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));

            writer.write("password");

            writer.newLine();

            writer.close();

            int errorcode=process.waitFor();

            System.out.println("errorcode:"+errorcode);

        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }

    }


}

StreamEater类

class StreamEater extends Thread
{


    private  InputStream inputStream=null;

    public StreamEater(InputStream stream)
    {
        this.inputStream=stream;
    }


    public void run()
    {
        System.out.println("Stream Eater thread started");

        Scanner scanner=new Scanner(new InputStreamReader(inputStream));

        String message="";

        StringBuilder sb=new StringBuilder("");

        try
        {
            System.out.println("before reading message");

            while(scanner.hasNextLine())
            {
                message=scanner.nextLine();

                sb.append(message);

                sb.append("\n");

            }

            scanner.close();

            System.out.println("after reading message  "+sb.toString());

        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }

        System.out.println("Stream Eater thread ended");

    }

}

有人能指出我犯了什么错误吗?还有其他方法可以将输入发送到bat文件吗?

2 个答案:

答案 0 :(得分:2)

此代码存在多个问题。我将首先回答您的直接问题。

传递密码参数(直接回答)

pgsql command强制用户以交互方式输入密码。 This SO answer describes two techniques to handle this:

  1. 使用.pgpass文件。您可以独立于程序创建此文件,也可以更改BAT文件以引用它。
  2. 设置一个PGPASSWORD environment variable。您可以更改BAT文件来执行此操作。 You can also set this in ProcessBuilder from your application,其代码类似于processBuilder.environment().put("PGPASSWORD ", "PASSWORD");

使用JDBC(改进代码)

使用JDBC,而不是让Java应用程序调用批处理文件。 JDBC确实存在,因此Java可以连接到数据库并针对该数据库运行查询。

这将避免调用批处理脚本的麻烦,并使您的应用程序直接与数据库进行交互。

答案 1 :(得分:0)

我认为您的线程将很快结束,因为扫描程序没有要读取的行。虽然它可能被阻止,但是您应该循环该线程。上面的答案也很好,但是请尝试这样做,而不会对您的代码造成太大影响:

while (stillReading) {
    while(scanner.hasNextLine())
         {
           message=scanner.nextLine();
           sb.append(message);
           sb.append("\n");

         }
Thread.sleep(1000);
}

主要问题是线程启动时InputStream中没有输入。