11

Java Web アプリケーションの起動時にデータベースをアップグレードする SQL スクリプトがたくさんあります。

ibatis scriptrunner を使用してみましたが、トリガーを定義するときに見事に失敗します。文字はステートメントの終わりを示しません。

これは基本的には機能しますが、特に「ビューの作成または置換」で可能なフォーマットとコメントを破壊します。

public class ScriptRunner {
private final DataSource ds;


public ScriptRunner(DataSource ds) {
    this.ds = ds;
}

public void run(InputStream sqlStream) throws SQLException, IOException {
    sqlStream.reset();
    final Statement statement = ds.getConnection().createStatement();
    List<String> sqlFragments = createSqlfragments(sqlStream);
    for (String toRun : sqlFragments) {
        if (toRun.length() > 0) {
            statement.execute(toRun);
        }
    }
}

private static List<String> createSqlfragments(InputStream sqlStream) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(sqlStream));

    List<String> ret = new ArrayList<String>();
    String line;
    StringBuilder script = new StringBuilder();
    while ((line = br.readLine()) != null) {
        if (line.equals("/")) {
            ret.add(removeMultilineComments(script));
            script = new StringBuilder();
        } else {
            //strip comments
            final int indexComment = line.indexOf("--");
            String lineWithoutComments = (indexComment != -1) ? line.substring(0, indexComment) : line;
            script.append(lineWithoutComments).append(" ");
        }
    }
    if (script.length() > 0) {
        ret.add(removeMultilineComments(script));
    }
    return ret;
}

private static String removeMultilineComments(StringBuilder script) {
    return script.toString().replaceAll("/\\*(.*?)\\*/", "").trim();
}

これを達成するためのきれいな方法はありますか?私が見たことのない休止状態に何かがありますか?または、何らかの方法で入力ストリームを sqlplus に渡すことはできますか? 書式設定に関する私の懸念に加えて、pl/sql 構文に関する知識が限られているため、このコードにエラーがないかどうかは疑問です。

4

6 に答える 6

7

以下のソリューションを参照用に使用してください。私は試してテストし、正常に実行しました。

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();
    }
}

このスニペット コードを使用して、実行してみてください。

以下のリンクで解決策について言及したユーザーに感謝します。

http://forums.sun.com/thread.jspa?threadID=5413026

よろしく | ニチン

于 2010-02-12T12:50:47.157 に答える
5

iBATISScriptRunnerにはsetDelimiter(String, boolean)メソッドがあります。これにより、「;」以外の文字列を使用できます。SQLステートメント間の区切り文字になります。

Oracle SQLスクリプトでは、ステートメントを「/」(スラッシュ)で区切ります。

Javaコードで、runScriptdo asetDelimter("/", false)を呼び出す前に、スクリプトランナーに「/」をステートメント区切り文字として認識するように指示します。

于 2008-10-24T08:45:01.413 に答える
3

少し前に同じ問題があり、解決策をグーグルで調べているときにあなたの質問に何度かぶつかったので、私はあなたに借りがあると思います—これまでの私の発見は次のとおりです。

つまり、 AntMavenのソースを開くと、単純なスクリプトには適した単純な正規表現ベースのスクリプト スプリッターを使用していることがわかりますが、ストアド プロシージャなどでは通常失敗します。iBATIS、c5 db 移行などと同じ話です。

問題は、複数の言語が関係していることです。「SQL スクリプト」を実行するには、(1) SQL、(2) PL/SQL、および (3) sqlplus コマンドを処理できる必要があります。

実行sqlplusすること自体は確かに方法ですが、構成が混乱するため、このオプションを回避しようとしました。

Alexandre Porcelli のパーサーなど、PL/SQL 用の ANTLR パーサーがあります。これらは非常に似ていますが、これまでのところ、それらに基づいた完全なドロップイン ソリューションを用意した人はいません。

最終的に、andのようないくつかの sqlplus コマンドを認識する別のアドホック スプリッターを作成することになりました。これはまだ醜いですが、ほとんどのスクリプトで機能します。(ただし、末尾にコメントがあるスクリプトなど、一部のスクリプトは機能しないことに注意してください。これは解決策ではなく、まだ解決策ではありません。)/EXIT--

于 2011-10-19T07:58:30.763 に答える
2

sqlplus : はい、できます。私は常に Xemacs(editor) 内から sqlplus を実行しています。したがって、解釈されたモードで sqlplus を実行し、コマンドを提供して出力を読み取ることもできます。

もう 1 つの方法は、Oracle ( http://www.oracle.com/technology/software/products/sql/index.html )から無料の Java ベースの SQL 開発者ツールをダウンロードすることです。Java プログラムのラッパーである sqlcli.bat ユーティリティが付属しています。このコマンド ライン ユーティリティを使用して作業を行うことができます。

要約すると、バックグラウンドで sqlplus を実行して、入力を提供し、出力を読み取ります (emacs のように)。

于 2008-10-14T10:07:38.007 に答える
0

あなたは他の人の実装を見ることができます。このリソースを参照してください:「JavaのオープンソースSQLクライアント」http://java-source.net/open-source/sql-clients

于 2008-10-19T09:59:35.880 に答える
0

独自のスクリプト ランナーを作成する場合は、Spring JDBC の SimpleJdbcTemplate ( http://static.springframework.org/spring/docs/2.0.x/reference/jdbc.html )を使用できます。

もちろん、Spring のリソースと同じようにスクリプトをロードすることもできます。

于 2008-10-14T10:41:35.770 に答える