Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从java运行oracle sql脚本_Java_Sql_Oracle_Scripting_Inputstream - Fatal编程技术网

从java运行oracle sql脚本

从java运行oracle sql脚本,java,sql,oracle,scripting,inputstream,Java,Sql,Oracle,Scripting,Inputstream,我有一堆sql脚本,当java web应用程序启动时,它们应该升级数据库 我尝试使用ibatis scriptrunner,但在定义触发器时失败了,其中“;”字符并不表示语句的结束 现在,我已经编写了自己版本的脚本运行程序,它基本上完成了这项工作,但破坏了可能的格式和注释,特别是在“创建或替换视图”中 公共类ScriptRunner{ 私有最终数据源ds; 公共ScriptRunner(数据源ds){ 这是1.ds=ds; } 公共void运行(InputStream sqlStream)引发S

我有一堆sql脚本,当java web应用程序启动时,它们应该升级数据库

我尝试使用ibatis scriptrunner,但在定义触发器时失败了,其中“;”字符并不表示语句的结束

现在,我已经编写了自己版本的脚本运行程序,它基本上完成了这项工作,但破坏了可能的格式和注释,特别是在“创建或替换视图”中

公共类ScriptRunner{
私有最终数据源ds;
公共ScriptRunner(数据源ds){
这是1.ds=ds;
}
公共void运行(InputStream sqlStream)引发SQLException、IOException{
sqlStream.reset();
final Statement Statement=ds.getConnection().createStatement();
List sqlFragments=createSqlfragments(sqlStream);
for(字符串toRun:sqlFragments){
if(toRun.length()>0){
语句。执行(toRun);
}
}
}
私有静态列表createSqlfragments(InputStream sqlStream)引发IOException{
BufferedReader br=新的BufferedReader(新的InputStreamReader(sqlStream));
List ret=new ArrayList();
弦线;
StringBuilder脚本=新建StringBuilder();
而((line=br.readLine())!=null){
如果(行等于(“/”){
ret.add(删除多元素(脚本));
脚本=新的StringBuilder();
}否则{
//条状评论
final int indexComment=line.indexOf(“--”);
字符串lineWithoutComments=(indexComment!=-1)?行。子字符串(0,indexComment):行;
script.append(无注释的行)。append(“”);
}
}
if(script.length()>0){
ret.add(删除多元素(脚本));
}
返回ret;
}
私有静态字符串删除多元素(StringBuilder脚本){
返回script.toString();
}
有没有一个干净的方法来证明这一点?在hibernate中有什么我没有看到的? 或者我可以通过某种方式将inputstream传递给sqlplus吗?
除了我对格式的担心之外,我还怀疑这段代码是否没有错误,因为我对pl/sql语法的了解有限。

sqlplus:可以。我一直在Xemacs(编辑器)中运行sqlplus。因此,您可以在解释模式下运行sqlplus,然后提供命令并读取输出

另一种方法是从oracle()下载免费的基于java的SQL developer工具。它附带一个sqlcli.bat实用程序,它是java程序的包装器。您可能希望使用此命令行实用程序来完成工作


总之,我会尝试在后台运行sqlplus,并提供它的输入和读取它的输出(就像emacs一样)。

如果您想编写自己的脚本运行程序,可以使用Spring JDBC的SimpleJDCtemplate()


当然,您也可以像在Spring中加载任何资源一样加载脚本。

您可以看到其他人的实现。请参阅此资源:“Java中的开源SQL客户端”

iBATIS ScriptRunner有一个
setDelimiter(String,boolean)
方法。这允许您使用除“;”之外的字符串作为SQL语句之间的分隔符

在Oracle SQL脚本中,用“/”(斜杠)分隔语句


在Java代码中,在调用
runScript
之前,请执行
setdelimeter(“/”,false)
,这将指示ScriptRunner将“/”识别为语句分隔符。

使用下面的解决方案供您参考,我已经尝试并测试了它并成功运行

private static String script_location = "";
private static String file_extension = ".sql";
private static ProcessBuilder processBuilder =null;

public static void main(String[] args) {
    try {
        File file = new File("C:/Script_folder");
        File [] list_files= file.listFiles(new FileFilter() {

            public boolean accept(File f) {
                if (f.getName().toLowerCase().endsWith(file_extension))
                    return true;
                return false;
            }
        });
        for (int i = 0; i<list_files.length;i++){
            script_location = "@" + list_files[i].getAbsolutePath();//ORACLE
            processBuilder = new ProcessBuilder("sqlplus",        "UserName/Password@database_name", script_location); //ORACLE
            //script_location = "-i" + list_files[i].getAbsolutePath();
            //  processBuilder = new ProcessBuilder("sqlplus", "-Udeep-Pdumbhead-Spc-de-deep\\sqlexpress-de_com",script_location);
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String currentLine = null;
            while ((currentLine = in.readLine()) != null) {
                System.out.println(" "  + currentLine);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }catch(Exception ex){
        ex.printStackTrace();
    }
}
私有静态字符串脚本_location=”“;
私有静态字符串文件_扩展名=“.sql”;
私有静态ProcessBuilder ProcessBuilder=null;
公共静态void main(字符串[]args){
试一试{
File File=新文件(“C:/Script_文件夹”);
File[]list_files=File.listFiles(新文件过滤器(){
公共布尔接受(文件f){
if(f.getName().toLowerCase().endsWith(文件扩展名))
返回true;
返回false;
}
});

因为(int i=0;我不久前也遇到过同样的问题,在谷歌搜索解决方案时多次碰到你的问题,所以我想我欠你一个人情,以下是我迄今为止的发现:

简而言之,没有现成的解决方案:如果您打开或打开源代码,您将看到他们使用的是一个简单的基于regexp的脚本拆分器,它适用于简单的脚本,但通常在存储过程等方面失败。iBATIS、c5 db迁移等也是如此

问题是,涉及到不止一种语言:为了运行“SQL脚本”,必须能够处理(1)SQL、(2)PL/SQL和(3)sqlplus命令

运行
sqlplus
本身确实是一种方式,但它会造成配置混乱,因此我们尝试避免使用此选项

有一些用于PL/SQL的ANTLR解析器,比如-它们非常接近,但到目前为止还没有人准备基于这些解析器的完整解决方案


最后,我们编写了一些sqlplus命令,如
/
EXIT
——这仍然很难看,但适用于我们的大多数脚本。(注意,尽管有些脚本,例如带有尾随
--
注释的脚本,不起作用,但它仍然是一个难题,不是一个解决方案。)

这看起来是一个不错的选择:)感谢sharingI,我正在使用ibatis-common-2.jar,但我还没有找到setDelimiter(String,boolean)方法,您使用的是哪个版本的ibatis?
private static String script_location = "";
private static String file_extension = ".sql";
private static ProcessBuilder processBuilder =null;

public static void main(String[] args) {
    try {
        File file = new File("C:/Script_folder");
        File [] list_files= file.listFiles(new FileFilter() {

            public boolean accept(File f) {
                if (f.getName().toLowerCase().endsWith(file_extension))
                    return true;
                return false;
            }
        });
        for (int i = 0; i<list_files.length;i++){
            script_location = "@" + list_files[i].getAbsolutePath();//ORACLE
            processBuilder = new ProcessBuilder("sqlplus",        "UserName/Password@database_name", script_location); //ORACLE
            //script_location = "-i" + list_files[i].getAbsolutePath();
            //  processBuilder = new ProcessBuilder("sqlplus", "-Udeep-Pdumbhead-Spc-de-deep\\sqlexpress-de_com",script_location);
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String currentLine = null;
            while ((currentLine = in.readLine()) != null) {
                System.out.println(" "  + currentLine);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }catch(Exception ex){
        ex.printStackTrace();
    }
}