我正在尝试使用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();
}
答案 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东西。
含义:在您当前的代码中,您有公共字段;并且您希望您的“按钮”代码使用这些字段。这是错误。相反,您的按钮代码应该在该接口的实例上调用(非静态!)方法。并且该接口的实现确保正确的事情发生。
你绝对不会继续当前的方法(一个类打开流,其他类只是“附加”到这些流;或者从它们读取)。