Apache Derby: Typ użytkownika AriaStringSet
Załóżmy, że chcemy umieścić w bazie danych Derby i odczytać z bazy danych Derby dowolny liczbowo podzbiór zbioru 'stringów’, zakładając, że każdy 'string’ jest elementem pewnego znanego zbioru o ściśle określonej liczbie elementów. np. Wybrać 5 imion z kalendarza imion. Kolejność 'stringów’ w podzbiorze musi być zachowana przy odczycie.
W rozwiązaniu problemu uczestniczą dwie klasy:
AriaStringSet
– klasa tworząca typ danychR064
– klasa uruchamiająca
AriaStringSet
package aderby.types; import java.io.*; import java.util.*; public class AriaStringSet implements Externalizable { private Set<String> totalSet; private final LinkedHashSet<String> elemSet; private String[] elems; public AriaStringSet() { totalSet = null; elems = null; elemSet = new LinkedHashSet<>(); } public AriaStringSet(Set<String> totalSet, String... elems) { this.totalSet = totalSet; this.elems = elems; elemSet = new LinkedHashSet<>(); elemSet.addAll(Arrays.asList(elems)); checkElems(); } /** * Sprawdza czy wszystkie elementy dodawane naleza do zbioru * * @throws IllegalArgumentException - jeśli element nie pasuje do zbioru */ public void checkElems() throws IllegalArgumentException { if (!totalSet.containsAll(elemSet)) { throw new IllegalArgumentException( " co najmniej jeden z elementów nie należy do zbioru"); } } public Set<String> getTotalSet() { return totalSet; } public LinkedHashSet<String> getElemSet() { return elemSet; } public String[] getElems() { Object[] temp = elemSet.toArray(); String[] temp1 = new String[temp.length]; for (int i = 0; i < temp1.length; i++) { temp1[i] = (String) temp[i]; } return temp1; } public void setData(Set<String> totalSet, String... elems) { this.totalSet = totalSet; this.elems = elems; elemSet.clear(); elemSet.addAll(Arrays.asList(elems)); checkElems(); } @Override public void writeExternal(ObjectOutput out) throws IOException { checkElems(); out.writeInt(elemSet.size()); for (String e : elemSet) { out.writeUTF(e); } } @Override public void readExternal(ObjectInput in) throws IOException { int len = in.readInt(); elems = new String[len]; for (int i = 0; i < len; i++) { elems[i] = in.readUTF(); } elemSet.clear(); elemSet.addAll(Arrays.asList(elems)); } }
R064
package aderby.types; import aderby.DerbyUtil; import java.sql.*; import java.util.*; public class R064_ARIASTRINGSET { //polecenie SQl tworzące typ 'StringSet' public static final String createTypeStringSet = "CREATE TYPE AriaStringSet " + "EXTERNAL NAME 'aderby.types.AriaStringSet' LANGUAGE JAVA"; //polecenie SQL tworzące tabele 'typy' w bazie 'r064' //Tabela zawiera 2 kolumny: //'id'INTEGER, automatycznie inkrementowana //'zestaw' umożliwiający dodanie obiektu klasy StringSet public static final String createTable = "CREATE TABLE typy(" + "id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS " + "IDENTITY(START WITH 1, INCREMENT BY 1), zestaw ARIASTRINGSET)"; public static void main(String[] args) { //uruchomienie Derby DerbyUtil.startDerbyEngine("EmbeddedDriver"); //utworzenie połączenia z bazą danych. Jeżeli baza nie istnieje //zostanie utworzona. Jeśli istnieje - zostanie użyta. Connection con = DerbyUtil.connectEmbeddedDB("C:/Przyklady/R064", ";create=true"); Statement stat = null; try { //utworzenie polecenia stat = con.createStatement(); //dodanie polecenia wsadowego tworzącego typ 'StringSet' stat.addBatch(createTypeStringSet); //dodanie polecenia wsadowego tworzącego tabele 'typy' stat.addBatch(createTable); //wykonanie poleceń stat.executeBatch(); } catch (SQLException e) { e.printStackTrace(); } PreparedStatement stmt = null; //polecenie SQL wstawiające dane do tabeli 'typy' //'id' jest dodawane automatycznie //'zestaw' jest dodawany ręcznie String insertSQL = "INSERT INTO typy (id, zestaw) values (DEFAULT,?)"; //utworzenie zbioru Set<String> zestaw = new TreeSet<>(); //dodanie elementów, z których można będzie dokonać wyboru zestaw.add("AA"); zestaw.add("BB"); zestaw.add("CC"); zestaw.add("DD"); zestaw.add("EE"); zestaw.add("FF"); zestaw.add("GG"); try { //utworzenie polecenia przygotowywanego stmt = con.prepareStatement(insertSQL); //wstawienie zestawu 3 z 7 dostępnych elementów stmt.setObject(1, new AriaStringSet(zestaw, "AA", "CC", "BB")); //wykonanie polecenia stmt.executeUpdate(); //usuniecie parametrów, niezbędne przy wstawianiu parametrów //w pętli. Tutaj jest zbędne stmt.clearParameters(); } catch (SQLException e1) { e1.printStackTrace(); } //polecenie SQl wybierające dane z bazy String selectSQL = "SELECT * FROM typy"; PreparedStatement pstm = null; ResultSet rs = null; int id = -1; String[] jset = null; try { //przygotowanie polecenia pstm = con.prepareStatement(selectSQL); //wykonanie polecenia rs = pstm.executeQuery(); //iteracja po zbiorze wynikowym while (rs.next()) { //pobranie 'id' id = rs.getInt("id"); //pobranie 'zestawu' jako tablicy elementów jset = ((AriaStringSet) rs.getObject("zestaw")).getElems(); } } catch (SQLException e) { e.printStackTrace(); } //wydrukowanie danych System.out.println("id: " + id); DerbyUtil.print(Objects.requireNonNull(jset)); //zamkniecie poleceń i połączenia DerbyUtil.close(rs); DerbyUtil.close(stat); DerbyUtil.close(stmt); DerbyUtil.close(pstm); DerbyUtil.close(con); //zatrzymanie silnika Derby DerbyUtil.shutdownDerbyEngine(); } }
Po uruchomieniu klasy na konsoli zobaczymy:
id: 1 [AA, CC, BB]
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.