IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

15. diel - Derby DB - Ukladanie / Získanie súborov

V minulej lekcii, Derby DB - Ukladanie / získanie jednoduchých dátových typu , sme sa venovali ukladanie rôznych primitívnych typov. V dnešnom DerbyDB tutoriálu si preberieme ukladanie súborov. Je jedno, aký typ súborov, či sa jedná o súbory hudobné (napr. Mp3, wav, ..), video (napr. Mkv, avi, ...), obrázky (napr. Jpg, gif, ...) alebo iba súbory dát či spúšťacie súbory (napr. txt, dát, xml, bin, exe, com, ...). DerbyDB podporuje 3 typy týchto súborov z celej SQL definície java.sql.Types. Najskôr si premyslite, aký súbor chcete do databázy ukladať, a potom mu priraďte jeden z podporovaných dátových typov nižšie:

  • BLOB (B Inari L arge OB ject): Jedná sa binárny súbor s premennou veľkosťou s maximálnou veľkosťou 2,147 GB
  • CLOB (C haracter L arge OB ject): Jedná sa znakový súbor v UNICODE s premennou veľkosťou s maximálnou veľkosťou 2,147 GB
  • XML (XML súbor): V DerbyDB práca s XML súborom nie je priamo podporovaná. V JDBC existuje objekt SQLXML, ktorý predstavuje náš XML súbor. DerbyDB tento objekt nemá priamo (a tak ako by mal byť) implementovaný, takže vždy bude null, a pri práci s ním sa zavolá výnimka. Najjednoduchším riešením je využívať XML súbor ako CLOB. XML súbor je súbor znakový a teda CLOB je logická voľba. Čo znamená, že pri tvorbe tabuľky stĺpec pre XML nastavíme ako CLOB. Avšak existuje aj možnosť, ako XML súbor cez DerbyDB použiť, a to cez XMLPARSE, ale je to trochu zdĺhavejšie.

My sa rozhodneme nevyužiť variantu CLOB (definícia stĺpce v tabuľke) pri uchovaní XML v riešenom príklade, ale zvolíme krkolomnejšie riešenie XMLPARSE, ktoré DerbyDB umožňuje. Pri tvorbe tabuľky definujeme stĺpec ako XML. Problémom tohto riešenia je, že XML sa do databázy uloží bez hlavičky (deklarácia), čo je úplne nevhodné. Stratíme tak zásadné metainformácie ako verzia XML, kódovanie znakovej sady a podobné, ktoré k XML patrí.

Vyriešime to veľmi jednoducho, samotnú deklaráciu XML načítame ako String a tú uložíme do databázy tiež. Pri získaní XML súboru z databázy potom iba daný String k XML súboru proste a jednoducho pridáme. Nejedná sa o úplne najvhodnejšie riešenie, ale ako príklad bohato stačí. Zaiste si potom všimnete, že pri spracovaní XML využívame getter / setter pre CLOB. To je nevyhnutné. Takže používanie XMLPARSE je prakticky zbytočné. CLOB funguje dobre a nemusíte riešiť problém s hlavičkou (deklaráciou) XML.

Dátový typ Java Syntax Dátový typ Derby JDBC metatyp (java.sql.Types) Poznámka
java.io.InputStream InputStream BLOB viz. JAVA API
java.io.InputStream InputStream CLOB viz. JAVA API
java.io.InputStream InputStream SQLXML viz. JAVA API Nie je plne podporovaný
Tentoraz si nebudeme ukazovať ukladanie súborov cez IJ, pretože to snáď ani nejde, možno cez nejaký komplikovanejšia skript.

Vytvorenie tabuľky programovo ako uzivatel10 a naplnenie tabuľky dátami

Vytvoríme si testovací príklad v Java SE projekt v IDE. V menu zvolíme File -> New -> Java Project. Pomenujeme projekt a nastavíme JRE Java8. Pridáme opäť externé knižnice do nášho projektu do CLASSPATH. Ide o tieto externé knižnice:

  • derbyclient.jar
  • derby.jar
  • derbytools.jar
  • derbyoptionaltools.jar
nastavenie Projektu - DerbyDb

Ako vidíte, do projektu sa pridali nutné knižnice. Navyše som v projekte vytvoril adresár vstupy/, kam som skopírovali vzorové súbory. Konkrétne jeden obrázok, jeden XML súbor a jeden súbor zdrojového kódu z Javy. Tieto súbory budeme ukladať do DerbyDB.

projekt - DerbyDb

Kód je koncepčne prakticky rovnaký ako v minulom príklade. Prihlásime sa ako uzivatel10 a vytvoríme tabuľku Soubory. Naplníme ju dátami, vyberieme dáta a uložíme do adresára výstupy/. Všetky súbory budeme mať uložené v objekte InputStream. Pretože, ako som vyššie uviedol, XMLPARSE nenačíta hlavičku (deklaráciu) XML súboru, tak ju uložíme (znakovo načítame) do StringBuilder a prevedieme do String ua do databázy ju uložíme ako VARCHAR:

package datab;
import java.io.*;
import java.sql.*;

public class Soubory {

    private static Connection connect = null;
    private static PreparedStatement statement = null;

    static {
        try { // nutne pridat do CLASSPATH - derbyclient.jar
            Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            System.out.println("Problem s nactenim driveru - nutne pridat do CLASSPATH - derbyclient.jar");
        }
    }

    private static void pripojeniDatabaze(String jmeno, String heslo) {
        try {
            connect = DriverManager.getConnection("jdbc:derby:C:/Program Files/JavaJDK08/db/bin/databaze10;user="
                    + jmeno + ";password=" + heslo + ";");
            System.out.println("Podarilo se pripojit k databazi10");
        } catch (Exception e) {
            System.err.println("Nepodarilo se pripojit k databazi10");
            if (connect == null) {
                System.exit(1);
            }
        }
    }

    private static void odpojimeDatabazi() {
        try {
            if (statement != null) {
                statement.close();
            }
            if (connect != null) {
                connect.close();
            }
            System.out.println("Podarilo se odpojit od databaze");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void vytvoreniTabulky(String s) {
        try {
            statement = connect.prepareStatement("create table " + s
                    + " (id INT not null primary key GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1), "
                    + " obrazekBlob BLOB(200K),souborClob CLOB(1K), souborXML XML, deklaraceXML VARCHAR (4096) )");
            statement.execute();
            System.out.println("Podarilo se vytvorit tabulku : " + s);
        } catch (SQLException e) {
            System.out.println("Nepovedlo se vytvorit tabulku :");
            e.printStackTrace();
        }
    }
    private static void naplneniDatTabulky(String s) {
        InputStream obrazekStream = null, souborStream = null, xmlStream = null,xmlDeclaration = null;
        String deklaraceXML=null;
        try {
            File soubor = new File("vstupy\\textura.png");
            obrazekStream = new FileInputStream(soubor);
            soubor = new File("vstupy\\CalculateFPSExample.java");
            souborStream = new FileInputStream(soubor);
            soubor = new File("vstupy\\jidlo.xml");
            xmlStream = new FileInputStream(soubor);
            xmlDeclaration = new FileInputStream(soubor);
            // ziskame deklaraci XML souboru do Stringu
            int ch;
            StringBuilder sb = new StringBuilder();
            while((ch = xmlDeclaration.read()) != '>')
                sb.append((char)ch);
            deklaraceXML = sb.toString()+">";
            System.out.println("Poradilo se nacist standardni soubory");
        } catch (Exception e1) {
            System.out.println("Neporadilo se nacist standardni soubory");
            e1.printStackTrace();
        }
        // Ulozime datove typy
        try {
            statement = connect.prepareStatement("INSERT INTO " + s + "(obrazekBlob,souborClob,souborXML,deklaraceXML) "
                    + "VALUES (?,?,XMLPARSE(DOCUMENT CAST(? AS CLOB) PRESERVE WHITESPACE),?)");
            statement.setBinaryStream(1, obrazekStream);
            statement.setAsciiStream(2, souborStream);
            statement.setAsciiStream(3, xmlStream);
            statement.setString(4,deklaraceXML);
            statement.execute();
            System.out.println("Podarilo se ulozit data");
        } catch (SQLException e) {
            System.out.println("Nepovedlo se ulozit data");
            e.printStackTrace();
        }
        try {
            obrazekStream.close();
            souborStream.close();
            xmlStream.close();
            System.out.println("Podarilo se ukoncit cteci streamy");
        } catch (IOException e) {
            System.out.println("Nepodarilo se ukoncit cteci streamy");
            e.printStackTrace();
        }
    }
    private static void vyjmemeDataZTakulky(String s) throws Exception {
        File newfile = null;
        try {
            Statement statement = connect.createStatement();
            ResultSet odpoved = statement.executeQuery("SELECT obrazekBlob,souborClob,XMLSERIALIZE(souborXML AS CLOB),deklaraceXML FROM " + s + " ORDER BY id");
            System.out.println("Podarilo se ziskat data CLOB,BLOB ");
            while (odpoved.next()) {
                // BLOB - nacteme a vytvorime soubor
                byte[] buff = new byte[1024];
                Blob ablob = odpoved.getBlob(1);
                newfile = new File("vystupy\\newBlob.jpg");
                InputStream is = ablob.getBinaryStream();
                FileOutputStream fos = new FileOutputStream(newfile);
                for (int b = is.read(buff); b != -1; b = is.read(buff)) {
                    fos.write(buff, 0, b);
                }
                is.close();
                fos.close();

                // CLOB - nacteme a vytvorime soubor
                buff = new byte[1024];
                Clob aclob = odpoved.getClob(2);
                newfile = new File("vystupy\\newClob.java");
                is = aclob.getAsciiStream();
                fos = new FileOutputStream(newfile);
                for (int b = is.read(buff); b != -1; b = is.read(buff)) {
                    fos.write(buff, 0, b);
                }
                is.close();
                fos.close();
                System.out.println("Podarilo data ulozit do souboru CLOB,BLOB");

                //  XML - ziskame hlavicku XML ze stringu
                String deklaraceXML = odpoved.getString(4);
                InputStream stream = new ByteArrayInputStream(deklaraceXML.getBytes(java.nio.charset.StandardCharsets.UTF_8));
                //  XML - nacteme
                buff = new byte[1024];
                aclob = odpoved.getClob(3);
                newfile = new File("vystupy\\newXML.xml");
                is = aclob.getAsciiStream();
                //  prevedeme inpustream do xml souboru
                fos = new FileOutputStream(newfile);
                for (int b = stream.read(buff); b != -1; b = stream.read(buff)) {
                    fos.write(buff, 0, b);
                }
                fos.write(System.getProperty("line.separator").getBytes());
                for (int b = is.read(buff); b != -1; b = is.read(buff)) {
                    fos.write(buff, 0, b);
                }

                is.close();
                fos.close();
                System.out.println("Podarilo data ulozit do souboru XML");
            }
            odpoved.close();
            System.out.println("Soubor se podarilo nacist - vznikl - vystupy/newBlob.jpg");
            System.out.println("Soubor se podarilo nacist - vznikl - vystupy/newClob.java.java");
            System.out.println("Soubor se podarilo nacist - vznikl - vystupy/newXML.xml");
        } catch (SQLException e) {
            System.out.println("Nepovedlo se ziskat/ulozit data do souboru");
            e.printStackTrace();
        }
    }

    private static void smazemeTabulku(String s) {
        try {
            statement = connect.prepareStatement("DROP TABLE " + s);
            statement.execute();
            System.out.println("Podarilo se smazat tabulku : " + s);
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("Nepodarilo se smazat tabulku : " + s);
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Start programu");
        pripojeniDatabaze("uzivatel10", "heslo10");
        vytvoreniTabulky("Soubory");
        naplneniDatTabulky("Soubory");
        vyjmemeDataZTakulky("Soubory");
        smazemeTabulku("Soubory");
        odpojimeDatabazi();
        System.out.println("Konec programu");
    }
}

Pretože XML súbor sa skladá v databáz z dvoch časti, je nutné pri zápise XML do súboru danú hlavičku do XML súboru vrátiť. To vykonáme štandardným zápisom cez FileOutputStream cez pole byte[]. Pretože je hlavička prvý, tak najskôr do súboru zapíšeme ako prvý. Potom vykonáme zápis odriadkovanie no a posledná prevedieme zápis tela (body) nášho XML súboru.

vykonané - DerbyDb

Ako vidíte, kód prebehne bez chyby. V budúcej lekcii, Derby DB - Ukladanie / Získanie objektov 1 (User Defined Type) , sa pozrieme na ukladanie a načítanie Java objektov z / do databázy.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 8x (271.1 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Predchádzajúci článok
Derby DB - Ukladanie / získanie jednoduchých dátových typu
Všetky články v sekcii
DerbyDb
Preskočiť článok
(neodporúčame)
Derby DB - Ukladanie / Získanie objektov 1 (User Defined Type)
Článok pre vás napísal Robert Michalovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Programuji převážně v Javě SE,EE a trochu nativním C a CUDA. více viz.https://cz.linkedin.com/in/robert-michalovic
Aktivity