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ý |
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
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.
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.
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