# Sinnvollste weg eine SQLite DB mit Android auslesen



## SchokoMuh (25. Feb 2021)

Hallo,
der Neuling ist mal wieder da und hat eine dumme Frage. Also gleich mal vorweg ich möchte keinen fertigen Code aber für einen Hinweis in welches Thema ich mich mehr einlesen sollte währe ich sehr dankbar.
Na dann komme ich jetzt mal zu meinem Problem. Ich habe eine SQLite DB in meine Android App integriert, die hat 5 Tables und insgesamt ca. 60 Spalten. Ich habe mir für jeden Table eine eigene Klasse mit Variablen angelegt um die ausgelesenen Daten zur Verarbeitung zu speichern. Das funktioniert soweit auch wirklich gut. Das Problem das ich aber jetzt habe ist das ich dem Nutzer die Möglichkeit geben möchte noch ein Paar Spalten hinzuzufügen, was ja an sich auch noch nicht schwierig ist aber wie Lese ich dann die DB aus weil in den Klassen zur Datenspeicherung für die neuen Spalten keine Variablen existieren. Die einzige Idee die ich habe währe das ich das Zwischenspeichern der Daten nicht mit normalen Variablen mache sondern mit ArrayList weil die ja eine Variable länge hat.
Ich währ sehr dankbar wenn mir jemand einen Tip geben könnte.

MFG


----------



## kneitzel (25. Feb 2021)

Also generell ist die erste Frage immer: Ist das Design evtl. verbesserungswürdig?

Da wäre dann aus meiner Sicht die Frage offen: Muss die Datenstruktur wirklich angepasst werden?
Ein Datenbankdesign kann ja vorsehen, dass Du:
- Die Tabelle für die Entity hast
- Eine Tabelle mit zusätzlichen Attributen
- Eine Tabelle, die Zuweisungen vorhält, also Entity, Attribut und Value.
Wenn der Typ vom Value frei gewählt werden kann, dann muss man sich überlegen, wie man das aufbauen möchte.
a) Man kann sich eine universelle Speicherform überlegen und das im Code abfangen. Dann ist in Value immer z.B. ein JSON String gespeichert. Und Attribut hat dann einen Typ und jeder Typ kann halt serialisieren / deserialisieren.... 
b) man kann das auch in der Datenbank aufnehmen. Dann hat man ggf. mehrere Tabellen oder Spalten um es aufzunehmen.

Aber bei solchen Designs hat die Applikation immer eine feste Datenbankstruktur, auf die zurück gegriffen wird.

Die Alternative, dass die Tabellen dynamisch angepasst werden, geht natürlich auch, aber dann hast Du es aus meiner Sicht etwas komplexer. Wobei das nur auf der Datenbankseite wäre. Auf der Codeseite würde ich die zusätzlichen Felder immer noch entsprechend aufnehmen. Das kann z,B. eine Map<String, Value> sein mit Value dann einer von Value abgeleiteten klasse mit dem Wert... (Da würde ich dann Code Teile rein packen, die wichtig werden könnten Evtl. notwendigkeiten beim lesen/speichern oder anzeigen ... Ich habe das noch nicht im Detail durchdacht, aber vermutlich wird da das eine oder andere notwendig werden ...)

Das einfach einmal paar Gedanken von mir ...


----------



## SchokoMuh (25. Feb 2021)

kneitzel hat gesagt.:


> Also generell ist die erste Frage immer: Ist das Design evtl. verbesserungswürdig?
> 
> Da wäre dann aus meiner Sicht die Frage offen: Muss die Datenstruktur wirklich angepasst werden?
> Ein Datenbankdesign kann ja vorsehen, dass Du:
> ...


Danke schonmal für die schnelle und wie immer super Antwort. Leider muss ich sagen das diesmal soviele begriffe vorkommen mit denen ich nichts anfangen kann, das ich erst heute abend wenn ich ruhe habe mich damit beschäftigen kann. Aber eine frage hab ich dann doch gleich, nach was muss ich suchen wenn ich für das "Map<String, Value>" eine Erklärung suche weil wenn ich das bei Google suche komm ich immer bei Google Maps raus und das ist ja nicht das was ich suche.


----------



## kneitzel (25. Feb 2021)

Such mal nach Java Map oder Java Collections.

Das sind paar wichtige Klassen, die man kennen sollte: List, Map und Set (wobei das nur Interfaces sind, die Implementationen sind dann z.B. ArrayList, HashMap, HashSet, ....)


----------



## SchokoMuh (26. Feb 2021)

Einen wunderschönen guten Morgen erstmal. Anstand muss sein 
Also ich habe mich letzte Nacht mal ein bisschen mit dem Thema Map beschäftigt leider hab ich Collection nicht mehr geschafft. Die Klasse Hashmap verwirrt mich noch ein bisschen aber das werde ich einfach mal ausprobieren. 
Ich weiß zwar immer noch nicht genau was ich alles brauche um die DB dynamisch zu gestallten aber habe die Idee das über eine zusätzliche DB zu machen in der in Spalte eins eine eindeutige ID vergeben ( Primary Key ), in Spalte zwei den Namen des Tables, in Spalte 3 die Spaltennamen der eigentlichen Datenbank und in Spalte 4 dann noch den Datentyp der der Spalte. 
Bitte korrigiert mich wenn ich falsch liege aber so sollte es ja kein Problem sein zur Laufzeit weitere Spalten zur DB hinzu zu fügen. Außerdem hab ich ja dann für jede Spalte eine eindeutige ID was das spätere arbeiten damit auch erleichtern sollte. Dann könnte ich danach ein List Objekt erstellen und die daten nach der ID zwischenspeichern um sie dann weiter zu verarbeiten.

Ich hoffe das das vom Gedanken her nicht ganz falsch ist. Ich möchte mich am Wochenende mal in ruhe damit beschäftigen und würde dann nächste Woche mal den Code zwecks Verbesserungsvorschlägen Posten.


----------



## Thallius (26. Feb 2021)

Datenbank Tabellen dynamisch zu verwalten halte ich immer für eine schlechte Idee. Du hast später unendlich viele verschiedene Datenbank Strukturen unterwegs in deinen Apps die du alle behandeln können must. Das ist das reinste wartungchaos.

Wie Kneitzel schon schrieb, wenn du variable Anzahl von Daten pro user haben willst, dann gibt es eben zwei Möglichkeiten:

1: Du erstellst eine Spalte mit JSON Inhalt in der du einfach ein JSON Object beliebiger Länge speichern kannst. Dieses kannst du jederzeit verändern. Also neue Attribute hinzufügen oder alte editieren/löschen.
Nachteil: Wenn Du in der Datenbank nach den Daten suchen willst wird es schnell langsam.

2: Du erstellst eine Tabelle mit den Spalten Key und Value und kannst dann dort beliebig viele rows speichern. Wenn die Attribute an verschiedene Objekte geknüpft werden sollen, kannst du der Tabelle noch eine Spalte für den Objekttypen hinzufügen. Dein Object erhält dann einfach eine ArrayList oder Hasmap in welche der Inhalt dieser Tabelle eingelesen wird.


----------



## SchokoMuh (3. Mrz 2021)

So es hat ein bisschen gedauert bis ich wieder weiter machen konnte. Hab die Datenbank jetzt fix erstellt so wie ihr es mir geraten habt. Funktioniert auch super hab mich halt an einem Beispiel Orientiert. Nur zum Verständnis hätte ich aber jetzt noch eine frage zu dem Beispiel das ich verwendet habe. Hoffe ihr könnt mir das verständlich erklären. Hier der Code:
[CODE lang="java" highlight="2"]public final class ContractExample{
    public ContractExample(){}

    public static abstract class TabUsers implements BaseColumns{
        public static final String TABLE_NAME = "Users";
        public static final String COL_NAMEVAL = "NameValue";
    }
}[/CODE]

Die Methode in Zeile 2 ist ja leer also sinnlos, aber was würde da den eigentlich rein kommen?


----------



## mihe7 (3. Mrz 2021)

Das in Zeile 2 ist keine Methode, sondern ein Konstruktor. Sein Zweck ist es, Objekte bei ihrer Erzeugung zu initialisieren. Hättest Du z. B. eine Instanzvariable, dann könntest Du deren Wert im Konstruktor initialisieren.

Der parameterlose Konstruktor wird Standardkonstruktor genannt. Dieser ist prinzipiell auch dann verfügbar, wenn man ihn nicht explizit im Code angibt, allerdings nur dann, wenn kein anderer Konstruktor (also einer mit Parametern) in der Klasse existiert. Sprich: hat man einen Konstruktor mit Parametern und will man auch den Standardkonstruktor zur Verfügung haben, dann muss man den Standardkonstruktor explizit im Code angeben. Gleiches gilt, wenn man die Sichtbarkeit ändern möchte.


```
public class X {
}
```
Hier existiert der Standardkonstruktor X() implizit, man kann also Objekte mit `new X();` erzeugen.


```
public class X {
    private String name;

    public X(String einName) {
        name = einName;
    }
}
```
Hier existiert nur der Konstruktor, der einen String als Parameter entgegennimmt. `new X("ABC");` ist also möglich, `new X();` dagegen nicht.



```
public class X {
    private String name;

    public X() {
        name = "Standard";
    }

    public X(String einName) {
        name = einName;
    }
}
```
Hier gibt es zwei Konstruktoren, so dass `new X();` genauso möglich ist, wie `new X("ABC");`. Im ersten Fall wird der parameterlose Konstruktor aufgerufen und somit die Instanzvariable `name` auf "Standard" gesetzt. Im zweiten Fall wird der andere Konstruktor aufgerufen und somit die Instanzvariable `name` auf den in `einName` übergebenen String gesetzt.


----------

