Apache Derby: przygotowanie bazy tylko do odczytu
Często korzystamy z baz danych, które nie zmieniają się lub zmieniają się bardzo rzadko. Takim przykładem jest np. lista adresów urzędów skarbowych czy wykaz pocztowych kodów adresowych.
Taką bazę możemy uczynić bazą tylko do odczytu.
Taka baza może być zapisana do pliku JAR lub ZIP.
Baza w postaci przygotowanego folderu lub w postaci pliku JAR czy ZIP może być zapisana na mediach tylko do odczytu, np. na płytce CD lub DVD.
Tutaj pokażę jak przygotować bazę do zapisu na płytce CD lub DVD.
Przygotowanie bazy
W pliku 'urzedy.txt’ znajduje się stara baza urzędów skarbowych. Jest to kilkaset adresów, które zajmują objętość kilkudziesięciu stron.
Tworzymy skrypt resources/sqls/r093.sql
Skrypt r093.sql
CREATE TABLE urzad(id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1), nazwa VARCHAR(128), kod VARCHAR(6), miejscowosc VARCHAR(128), ulica VARCHAR(128), dom VARCHAR(16), cit VARCHAR(26), vat VARCHAR(26), pit VARCHAR(26), ind VARCHAR(26), jb VARCHAR(26), wyd VARCHAR(26), doch VARCHAR(26), bank VARCHAR(64), vatue1 VARCHAR(26), vatue2 VARCHAR(26), pitstp VARCHAR(26) );
Niestety w skrypcie nie będziemy wprowadzali danych, gdyż kosztowałoby nas to zbyt dużo pracy. Musimy stworzyć metodę, która wczyta dane z pliku tekstowego.
Tworzymy klasę R093_rom
która utworzy baze danych i wczyta dane.
Klasa R093_rom.java
package aderby.specyf; import aderby.DerbyUtil; import java.io.*; import java.sql.*; import java.util.*; @SuppressWarnings("SameParameterValue") public class R093_rom { private static Connection con; public static void main(String[] args) { DerbyUtil.setReadOnlyProps(); DerbyUtil.startDerbyEngine(DerbyUtil.embdriver); con = DerbyUtil.connectEmbeddedDB("C:/Przyklady/baza_urzedow", ";create=true"); DerbyUtil.jdbcRunScript("aderby/src/resources/sqls/r093.sql", con); ArrayList<String> al = wczytajTxt("aderby/src/resources/txts/urzedy.txt"); tokenize(al); DerbyUtil.close(con); DerbyUtil.shutdownEmbeddedDB("baza_urzedow"); DerbyUtil.shutdownDerbyEngine(); } private static ArrayList<String> wczytajTxt(String file) { ArrayList<String> als = new ArrayList<>(); try { FileReader fr = new FileReader(file); try (fr; BufferedReader in = new BufferedReader(fr)) { String s; while ((s = in.readLine()) != null) { als.add(s); } } } catch (IOException ioe) { throw new RuntimeException(ioe); } return als; } private static void tokenize(ArrayList<String> als) { String insertSQL = "insert into urzad values(DEFAULT,?,?,?,?,?,?,?," + "?,?,?,?,?,?,?,?,?)"; StringTokenizer st; String nazwa1 = null; String kod1 = null; String miejscowosc1 = null; String ulica1 = null; String dom1 = null; String cit1 = null; String vat1 = null; String pit1 = null; String ind1 = null; String jb1 = null; String wyd1 = null; String doch1 = null; String bank1 = null; String vatue11 = null; String vatue21 = null; String pitstp1 = null; PreparedStatement stmt = null; for (String al : als) { st = new StringTokenizer(al, ","); while (st.hasMoreTokens()) { nazwa1 = st.nextToken().trim(); kod1 = st.nextToken().trim(); miejscowosc1 = st.nextToken().trim(); ulica1 = st.nextToken().trim(); dom1 = st.nextToken().trim(); cit1 = st.nextToken().trim(); vat1 = st.nextToken().trim(); pit1 = st.nextToken().trim(); ind1 = st.nextToken().trim(); jb1 = st.nextToken().trim(); wyd1 = st.nextToken().trim(); doch1 = st.nextToken().trim(); bank1 = st.nextToken().trim(); vatue11 = st.nextToken().trim(); vatue21 = st.nextToken().trim(); pitstp1 = st.nextToken().trim(); } try { stmt = con.prepareStatement(insertSQL); stmt.setString(1, nazwa1); stmt.setString(2, kod1); stmt.setString(3, miejscowosc1); stmt.setString(4, ulica1); stmt.setString(5, dom1); stmt.setString(6, cit1); stmt.setString(7, vat1); stmt.setString(8, pit1); stmt.setString(9, ind1); stmt.setString(10, jb1); stmt.setString(11, wyd1); stmt.setString(12, doch1); stmt.setString(13, bank1); stmt.setString(14, vatue11); stmt.setString(15, vatue21); stmt.setString(16, pitstp1); stmt.executeUpdate(); stmt.clearParameters(); } catch (SQLException e) { e.printStackTrace(); } } DerbyUtil.close(stmt); } }
Po uruchomieniu klasy baza danych baza_urzedow znajdzie się w folderze c:/Przyklady
Przygotowanie bazy danych tylko do odczytu
1. Utwórz bazę danych na dysku twardym – zrobiliśmy to przed chwilą. Podczas przygotowywania bazy należy zwrócić uwagę aby zakończone zostały wszelkie transakcje a baza i silnik zostały zamknięte. Jeśli coś pozostało niezakończone zostanie podjęta próba dtworzenia bazy danych, ale odtworzenie na nośniku CD lub DVD albo w pliku archiwum – jest niemożliwe.
2. Sprawdzamy czy w folderze głównym bazy danych znajduje się folder tmp. Jeśli jest należy go usunąć. Jeśli ten folder pozostanie – przy następnym uruchomieniu system podejmie próbę usunięcia go – i wyrzuci błąd ponieważ nie będzie to możliwe.
Jak widać w naszym folderze go nie ma (Rys. 281).
3. Ponieważ folder tmp może być utworzony, a na CD lub DVD jest to niemożliwe, należy zmienić miejsce tworzenia tego folderu, tak aby zachodziło na dysku twardym. W tym celu należy ustawić właściwość:
derby.storage.tempDirectory
Ponieważ w dziennikach zapisywane są również informacje o błędach, również dzienniki muszą być zapisane na dysku twardym. Aby to zrobić należy ustawić zmienną systemową:
derby.stream.error.file
Możemy to zrobić przy użyciu metody DerbyUtil.setReadOnlyProps()
public static void setReadOnlyProps() { System.setProperty("derby.storage.tempDirectory", "C:/temp/mytemp"); System.setProperty("derby.stream.error.file", "C:/temp/mylog.log"); }
Jeżeli baza danych zostanie przeniesiona np. na inny komputer, aplikacja wykorzystująca bazę powinna dla niej ustawić obie powyższe właściwości w systemie operacyjnym.
Nasza baza jest przygotowana do zamknięcia w pliku JAR lub ZIP i do zapisania na nośniku CD albo DVD.
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.