试图从java运行sql命令

时间:2016-09-12 08:00:53

标签: java sql cmd processbuilder

我正在尝试使用ProcessBuilder从java运行sql命令。我的问题是我不能使用来自不同功能的相同cmd。 例如,我想按下按钮时运行一个sql文件。之后,我想保持与sql plus的连接,并通过按其他按钮提交或回滚事务。如何将进程从按钮保持到其他按钮?

我的第一个按键代码:

public class MyExec {

    public static ProcessBuilder builder;
    public static Process p;
    public static BufferedReader bri;
    public static BufferedReader bre;
    public static BufferedWriter p_stdin;

     public static void executeScript(String scriptName, String alias, String path, TextArea txtArea) throws IOException {

     //obtaining sql script from a share folder
      NtlmPasswordAuthentication userCred = new NtlmPasswordAuthentication("domain",
                    "user", "pass");
      SmbFile smbFile=new SmbFile("path"  + scriptName, userCred);
      File file = new File("D://" + scriptName);
      try (InputStream in = smbFile.getInputStream()) {
        Files.copy(smbFile.getInputStream(), file.toPath());
      }

      //init shell
      builder = new ProcessBuilder( "cmd" );
      builder.redirectErrorStream(true);
      try {
        p = builder.start();
      } catch (IOException e) {
        System.out.println(e);
      }
      //get stdin of shell
      p_stdin =new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));

      //executing commands in cmd
      try {
        p_stdin.write("sqlplus sys/sys@" + alias +" as sysdba");
        p_stdin.newLine();
        p_stdin.flush();
        p_stdin.write("@"+file.toPath());
        p_stdin.newLine();
        p_stdin.flush();
      } catch (IOException e) {
        System.out.println(e);
      }

      // write stdout of shell (=output of all commands)
      String line;
      bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
                   bre = new BufferedReader(new InputStreamReader(p.getErrorStream()));
      while ((line = bri.readLine()) != null) {
        txtArea.appendText(line + "\n");
        System.out.println(line + "\n");
      }                
      while ((line = bre.readLine()) != null) {
        txtArea.appendText(line + "\n");
        System.out.println(line + "\n");
      }

      System.out.println("Done.");
    }

}

第二个按钮代码:

Thread t1 = new Thread(new Runnable() {
   public void run() {
     //commit the sql script which was run with the first button
     try {
       MyExec.p_stdin.write("commit");
       MyExec.p_stdin.newLine();
       MyExec.p_stdin.flush();
       MyExec.p_stdin.write("exit");
       MyExec.p_stdin.newLine();
       MyExec.p_stdin.flush();

       //output the result of commiting sql script
       String line;
       BufferedReader bri = new BufferedReader(new InputStreamReader(MyExec.p.getInputStream()));
       BufferedReader bre = new BufferedReader (new InputStreamReader(MyExec.p.getErrorStream()));
        while ((line = MyExec.bri.readLine()) != null) {
          txtArea.appendText(line + "\n");
          System.out.println(line + "\n");
        }
        MyExec.bri.close();
        while ((line = MyExec.bre.readLine()) != null) {
          txtArea.appendText(line + "\n");
          System.out.println(line + "\n");
        }
        MyExec.bri.close();
        System.out.println("Done.");
     } catch (IOException e1) {
        e1.printStackTrace();
     }

    }
    });
      //event on Commit button, running the thread above
    public void commit(ActionEvent e) {   
      t1.start();   
    }

1 个答案:

答案 0 :(得分:0)

Serg的评论为您提供了正确的方向:您需要在此处明确分离关注点。你不会写一个应用程序以某种方式在一个地方做所有事情。

首先定义一个接口,例如

interface SqlProvider {
  public void connectConnection() ... 
  public void beginTransaction() ...
  public void commit() ..
  public void rollback()
  public void endTransaction()
  public voide closeConnection()  

每个人都有合理的参数和投掷列表。

然后你开始实现那些接口;类似于你目前在MyExec中所做的事情;但是:你隐藏来自界面用户的所有ProcessBuilder东西。

含义:在您当前的代码中,您有公共字段;并且您希望您的“按钮”代码使用这些字段。这是错误。相反,您的按钮代码应该在该接口的实例上调用(非静态!)方法。并且该接口的实现确保正确的事情发生。

你绝对不会继续当前的方法(一个类打开流,其他类只是“附加”到这些流;或者从它们读取)。

相关问题