Zielony Smok - logo witryny

Apache Derby: Uruchamianie skryptów SQL

Tworzenie skryptów SQL i ij opisaliśmy wcześniej.

Uruchamianie skryptów SQL

Skrypty ij i SQL uruchamiamy przy użyciu narzędzia ij, używając polecenia run.
Opisaliśmy to tutaj. Przy uruchamianiu skryptów SQL musimy wcześniej połączyć się z baza danych. Przy uruchamianiu skryptów ij połączenie jest ustanawiane w skrypcie.

W języku Java możemy skorzystać z metody (która powinna być dodana do DerbyUtil.java):

 //---------------------------- R036 -----------------------------------

    /**
     * Uruchamia skrypt SQL. Skrypt może być wykonany z poziomu JDBC jak tutaj
     * albo z poziomu narzędzia ij
     *
     * @param scriptFile - sciezka do skryptu, który należy uruchomic
     * @param con        - połączenie z bazą, wykonującą zadanie.
     * @return - true - jeśli skrypt został wykonany
     */
    public static boolean runScript(String scriptFile, Connection con) {
        FileInputStream fileStream = null;
        try {
            fileStream = new FileInputStream(scriptFile);
            int result = org.apache.derby.tools.ij.runScript(con, fileStream, "UTF-8", System.out,
                    "UTF-8");
            //System.out.println("Result code is: " + result);
            return (result == 0);
        } catch (FileNotFoundException | UnsupportedEncodingException e) {
            return false;
        } finally {
            close(fileStream);
        }
    }

W środowisku nie zmodularyzowanym do Java 8 włącznie nie ma problemów przy uruchamianiu skryptu. Skrypt działa bez zarzutu.

W środowisku zmodularyzowanym pojawia się problem, gdyż moduł org.apache.derby.tools nie eksportuje pakietu org.apache.derby.tools do do modułu aderby. Aby kod uruchomić konieczne jest dodanie do opcji kompilatora linii:
-add-exports=org.apache.derby.tools/org.apache.derby.tools=aderby.

W IntelliJ IDEA ustawiamy to w Settings w dziale Build,Execution,Deployment, opcja JavaCompiler (Rys. 269):

Ustawienie kompilatora w IntelliJ IDEA
Ustawienie kompilatora w IntelliJ IDEA
Klasa R036.java
package aderby.sqls.scripts;

import aderby.DerbyUtil;

import java.sql.*;

public class R036 {
    public static void main(String[] args) {
        DerbyUtil.startDerbyNetworkServer("localhost", 1527);
        DerbyUtil.startDerbyEngine("ClientDriver");
        Connection con = DerbyUtil.connectEmbeddedDB("C:/Przyklady/R036", ";create=true");
        DerbyUtil.runScript("aderby/src/resources/sqls/temperatura.sql", con);
        Statement stat = null;
        ResultSet rs;
        try {
            stat = con.createStatement();
            rs = stat.executeQuery("SELECT AVG(val) FROM temperatura");
            while (rs.next()) {
                System.out.println(rs.getDouble(1));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        DerbyUtil.close(stat);
        DerbyUtil.close(con);
        DerbyUtil.shutdownDerbyEngine();
        DerbyUtil.shutdownDerbyNetworkServer();
    }
}

Niestety po uruchomieniu klasy, mimo prawidłowego ustawienia opcji dla kompilatora na konsoli pojawia się informacja:

Exception in thread "main" java.lang.IllegalAccessError: class aderby.DerbyUtil (in module aderby) cannot access class org.apache.derby.tools.ij (in module org.apache.derby.tools) because module org.apache.derby.tools does not export org.apache.derby.tools to module aderby
	at aderby/aderby.DerbyUtil.runScript(DerbyUtil.java:557)
	at aderby/aderby.sqls.R036.main(R036.java:12)
Skrypt temperatura.sql
CREATE TABLE temperatura(
       id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1),
       val DOUBLE
);
CREATE INDEX i_val ON temperatura (val ASC);

INSERT INTO temperatura (val) VALUES (37.8);
INSERT INTO temperatura (val) VALUES (39.7);
INSERT INTO temperatura (val) VALUES (36.6);
INSERT INTO temperatura (val) VALUES (33.2);
INSERT INTO temperatura (val) VALUES (39.2);
INSERT INTO temperatura (val) VALUES (40.6);
INSERT INTO temperatura (val) VALUES (41.2);
INSERT INTO temperatura (val) VALUES (40.1);
INSERT INTO temperatura (val) VALUES (39.8);
INSERT INTO temperatura (val) VALUES (38.9);
INSERT INTO temperatura (val) VALUES (38.3);
INSERT INTO temperatura (val) VALUES (37.9);
INSERT INTO temperatura (val) VALUES (37.4);
INSERT INTO temperatura (val) VALUES (37.1);
INSERT INTO temperatura (val) VALUES (36.8);
INSERT INTO temperatura (val) VALUES (36.7);
INSERT INTO temperatura (val) VALUES (36.6);

Na razie nie wiem dlaczego prawidłowy kod nie działa. Nie wiem czy to błąd IntelliJ czy mój, jeszcze niezidentyfikowany błąd. Gdy dowiem się natychmiast uzupełnię ten wpis.

Inne możliwości

1. Można rozpakować bibliotekę tools Apache Derby i kod eksportu dodać bezpośrednio do pliku module-info.java.

2. Napisać uproszczony parser skryptów SQL. Ponieważ wymaga to znajomości JDBC pokażę jak to zrobić przy omawianiu JDBC.

To już jest zrobione. Zajrzyj tutaj.

Pliki do ściągnięcia

Aktualny (tworzony narastająco) plik module-info.java

Aktualny (tworzony narastająco) plik DerbyUtil.java

Pliki tworzone narastająco zastępują poprzednie pliki o tej samej nazwie i działają dla wszystkich wcześniej opublikowanych przykładów we wszystkich wpisach w projekcie. W przypadku pliku module-info.java może być potrzebne skreślenie niepotrzebnych wpisów.