2008-10-14 4 views
9

Ich habe eine Reihe von SQL-Skripten, die die Datenbank aktualisieren sollte, wenn die Java-Webanwendung gestartet wird.Run Oracle SQL-Skript von Java

Ich habe versucht mit dem ibatis scriptrunner, aber es scheitert herrlich bei der Definition von Triggern, wo die ";" Zeichen markiert kein Ende der Aussage.

jetzt habe ich meine eigene Version eines Script-Runner geschrieben, der im Grunde genommen die Aufgabe erledigt, aber mögliche Formatierungen und Kommentare zerstört, besonders in "create or replace view".

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

Gibt es einen sauberen Weg, dies zu erreichen? Gibt es etwas im Winterschlaf, das ich nicht gesehen habe? oder kann ich irgendwie einen Eingangsstrom an sqlplus übergeben? neben meinen Sorgen über die Formatierung bezweifle ich, dass dieser Code fehlerfrei ist, da ich begrenzte Kenntnisse über die pl/SQL-Syntax habe.

Antwort

2

sqlplus: ja du kannst. Ich laufe sqlplus von Xemacs (Redakteur) die ganze Zeit. So können Sie sqlplus in einem interpretierten Modus ausführen und dann Befehle bereitstellen und die Ausgabe lesen.

Eine andere Möglichkeit besteht darin, das kostenlose Java-basierte SQL-Entwicklungstool von Oracle (http://www.oracle.com/technology/software/products/sql/index.html) herunterzuladen. Es kommt mit einem sqlcli.bat-Dienstprogramm, das ein Wrapper über ein Java-Programm ist. Sie können dieses Befehlszeilendienstprogramm verwenden, um Ihre Arbeit zu erledigen.

zusammenfassend, würde ich versuchen, sqlplus im Hintergrund laufen und bieten ihre Eingabe und Lesen ihrer Ausgabe (wie Emacs tut).

4

Der iBATIS ScriptRunner verfügt über eine setDelimiter(String, boolean)-Methode. Dadurch können Sie eine andere Zeichenfolge als ";" um das Trennzeichen zwischen SQL-Anweisungen zu sein.

In Ihrem Oracle SQL-Skript trennen Sie die Anweisungen mit einem "/" (Schrägstrich).

Geben Sie in Ihrem Java-Code vor dem Aufruf der runScript eine setDelimter("/", false) an, die den ScriptRunner anweist, "/" als Anweisungstrennzeichen zu erkennen.

+0

Ich verwende ibatis-common-2.jar und ich habe setDelimiter (String , boolean) Methode, Welche Version von iBatis verwenden Sie? –

7

Verwenden Sie unter Lösung für Ihre Referenz, ich habe versucht und getestet und läuft erfolgreich.

Verwenden Sie diesen Code-Schnipsel und versuchen Sie es auszuführen.

Thanx an Benutzer erwähnt die Lösung in den folgenden Link:

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

Grüße | Nitin

+1

das sieht nach einer guten Alternative aus :) Danke fürs Teilen –

3

Hatte das gleiche Problem nicht so lange her, stieß auf Ihre Frage mehrmals während für eine Lösung googeln, so dass ich denke, ich schulde dir-hier sind meine Ergebnisse so weit:

Kurz gesagt, gibt es keine fertige Lösungen dafür: Wenn Sie Ant oder Maven Quellen öffnen, werden Sie sehen, dass sie einen einfachen Regexp-basierten Skript-Splitter verwenden, der für einfache Skripte in Ordnung ist, aber normalerweise nicht funktioniert Gespeicherte Prozeduren. Die gleiche Geschichte mit iBATIS, c5 db Migrationen, etc.

Das Problem ist, es gibt mehr als eine Sprache beteiligt: ​​um "SQL Scripts" ausführen zu können, muss man in der Lage sein, (1) SQL, (2) PL/SQL und (3) sqlplus-Befehle.

Running sqlplus selbst ist zwar der Weg, aber es schafft Konfiguration Chaos, also haben wir versucht, diese Option zu vermeiden.

Es gibt ANTLR-Parser für PL/SQL, wie zum Beispiel Alexandre Porcelli's one - das sind sehr nahe, aber niemand hat eine vollständige Drop-In-Lösung basierend auf diesen bisher vorbereitet.

Wir haben geschrieben yet another ad hoc splitter, die einige sqlplus Befehle wie / und EXIT bekannt ist - es ist immer noch hässlich, aber funktioniert für die meisten unserer Skripte. (Beachten Sie, dass einige Skripts, z. B. mit abschließenden -- Kommentaren, nicht funktionieren - es ist immer noch ein Kludn, keine Lösung.)