Datenbank wie richtig ?

Z

zumafx

Fortgeschrittenes Mitglied
58
Hallo,
ich programmiere eigentlich schon seit Jahren, allerdings erst seit ein paar Tagen für Android. Ich habe eine kleine App erstellt, in der ich ein paar Daten erfasse und die in einer anderen Activity anzeige. Soweit, sogut.
Nun möchte ich aber die Daten in einer Datenbank speichern und da bin ich wohl zu doof, jedenfalls hab ich den ganzen Tag gelesen und getestet, aber ich kriege es einfach nicht ans laufen :(

hier mal meine Codeschnipsel:
dbHandler.java
Code:
package com.zumafx.Bipo;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DbHandler extends SQLiteOpenHelper {

    // Datenbank Version
    private static final int DATABASE_VERSION = 2;

    // DatenbankName
    private static final String DATABASE_NAME = "Stimmungen";

    // TabellenName
    private static final String TABLE_NAME = "Stimmung";

    // Spaltennamen Tabelle Stimmung
    private static final String Field_Id        = "id";
    private static final String Field_Tag       = "Tag";
    private static final String Field_Monat     = "Monat";
    private static final String Field_Jahr      = "Jahr";
    private static final String Field_Zustand   = "Zustand";
    private static final String Field_Stimmung  = "Stimmung";
    private static final String Field_Gereitzt  = "Gereitzt";
    private static final String Field_Text      = "Text";

    public DbHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Tabelle erzeugen
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_TABLE = "CREATE TABLE " +
                TABLE_NAME + "(" +
                Field_Id + " INTEGER PRIMARY KEY," +
                Field_Tag + " INTEGER,"+
                Field_Monat + " INTEGER," +
                Field_Jahr + " INTEGER,"+
                Field_Zustand + " TEXT," +
                Field_Stimmung + " TEXT," +
                Field_Gereitzt + " TEXT," +
                Field_Text + " TEXT" +")";
        db.execSQL(CREATE_TABLE);
    }

    // Upgrade Datenbank
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // ToDo: Alte Daten sichern
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
        // ToDo: Alte Daten wieder einlesen
    }

    // Stimmung einfügen
    public void addStimmung(StimmungDs Stimmung) {
        SQLiteDatabase db = this.getWritableDatabase();

        int id = getStimmungenCount(db);
        id++;
        ContentValues values = new ContentValues();
        values.put(Field_Id, id);
        values.put(Field_Tag, Stimmung.getTag());
        values.put(Field_Monat, Stimmung.getMonat());
        values.put(Field_Jahr, Stimmung.getJahr());
        values.put(Field_Zustand, Stimmung.getZustand());
        values.put(Field_Stimmung, Stimmung.getStimmung());
        values.put(Field_Gereitzt, Stimmung.getGereitzt());
        values.put(Field_Text, Stimmung.getText());

        db.insert(TABLE_NAME, null, values);
        db.close();
    }

    // Einen DatenSatz lesen
    public StimmungDs getStimmung(int id) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_NAME, new String[] {
                Field_Id,
                Field_Tag,
                Field_Monat,
                Field_Jahr,
                Field_Zustand,
                Field_Stimmung,
                Field_Gereitzt,
                Field_Text }, Field_Id + "=?",
                new String[] { String.valueOf(id) },
                null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        StimmungDs st = new StimmungDs(
                Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)),
                Integer.parseInt(cursor.getString(2)),
                Integer.parseInt(cursor.getString(3)),
                cursor.getString(4),
                cursor.getString(5),
                Boolean.parseBoolean(cursor.getString(6)),
                cursor.getString(7));
        db.close();
        return st;
    }

    // Alle Datensätze holen
    public List<StimmungDs> getAlleStimmungen() {
        List<StimmungDs> StimmungList = new ArrayList<StimmungDs>();
        String selectQuery = "SELECT  * FROM " + TABLE_NAME;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if (cursor.moveToFirst()) {
            do {
                StimmungDs st = new StimmungDs();
                st.setId(Integer.parseInt(cursor.getString(0)));
                st.setTag(Integer.parseInt(cursor.getString(1)));
                st.setMonat(Integer.parseInt(cursor.getString(2)));
                st.setJahr(Integer.parseInt(cursor.getString(3)));
                st.setZustand(cursor.getString(4));
                st.setStimmung(cursor.getString(5));
                st.setGereitzt(Boolean.parseBoolean(cursor.getString(6)));
                st.setText(cursor.getString(7));

                StimmungList.add(st);
            } while (cursor.moveToNext());
        }
        cursor.close();
        db.close();
        return StimmungList;
    }

    // Update eines Datensatzes
    public int updateStimmung(StimmungDs Stimmung) {
        SQLiteDatabase db = this.getWritableDatabase();
        int ok;
        ContentValues values = new ContentValues();
        values.put(Field_Id, Stimmung.getId());
        values.put(Field_Tag, Stimmung.getTag());
        values.put(Field_Monat, Stimmung.getMonat());
        values.put(Field_Jahr, Stimmung.getJahr());
        values.put(Field_Zustand, Stimmung.getZustand());
        values.put(Field_Stimmung, Stimmung.getStimmung());
        values.put(Field_Gereitzt, Stimmung.getGereitzt());
        values.put(Field_Text, Stimmung.getText());

        ok = db.update(TABLE_NAME, values, Field_Id + " = ?",
                new String[] { String.valueOf(Stimmung.getId()) });
        db.close();
        return ok;
    }

    // Datensatz löschen
    public void deleteStimmung(StimmungDs Stimmung) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_NAME, Field_Id + " = ?",
                new String[] { String.valueOf(Stimmung.getId()) });
        db.close();
    }

    // Anzahl Einträge holen
    public int getStimmungenCount(SQLiteDatabase db) {
        int Anzahl = 0;
        String countQuery = "SELECT  * FROM " + TABLE_NAME;
        Cursor cursor = db.rawQuery(countQuery, null);
        Anzahl = cursor.getCount();
        cursor.close();
        db.close();
        return Anzahl;
    }
}
so dachte ich zu speichern
Code:
....
        DbHandler db = new DbHandler(this);
        StimmungDs StDs = new StimmungDs();
        StDs.setTag(vday);
        StDs.setMonat(vmonth);
        StDs.setJahr(vyear);
        StDs.setZustand(Auswahl);
        StDs.setStimmung(stimmung);
        StDs.setGereitzt(cb.isChecked());
        StDs.setText(message);
        db.addStimmung(StDs);
....
und so wollte ich wieder auslesen
Code:
   DbHandler db = new DbHandler(this);
   List<StimmungDs> ls = db.getAlleStimmungen();

   ListView lv = (ListView) findViewById(R.id.Liste);
   ListAdapter adapter = new ArrayAdapter<>(getApplicationContext(),
                                                android.R.layout.simple_list_item_1, ls);
   lv.setAdapter(adapter);
leider hab ich noch keine Ahnung wie man in AndroidStudio debuggt, aber auch wenn, bin ich wohl noch zu sehr Android-Frischling, um herrauszufinden, wie ich meine Daten in der DB speichere und wieder auslese.
Dank an alle, die bis hier gelesen haben und auch evtl. mir helfen können
 
hallo Jaiel,
danke für die schnelle Antwort, aber das hilft irgendwie auch nicht wirklich :(

Wenn ich wie in dem Beispiel auf der von dir verlinkten Seite folgendes mache/abtippe:

Code:
public class DbHandler extends SQLiteOpenHelper {

    private Context context;

... Var's für die Texte (DATABASE_Name, usw);

    DbHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    }

    // Tabelle erzeugen
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
    }

    // Upgrade Datenbank
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // ToDo: Alte Daten sichern
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
        // ToDo: Alte Daten wieder einlesen
    }
}
wird mir angezeigt, das die Variable "context" nicht genutzt wird.
dabei hab ich doch explizit

this.context = context;

angegeben ?

Ich hätte halt auch gerne alle DB-Funktionen in der selben Class stehen,
also erzeugen, schreiben, lesen, etc.
Daher hab ich gedacht, das ich doch auch in der DbHandler-Class die weiteren Methoden für die jeweiligen Funktionen implementieren kann ?

z.b.
Code:
// Stimmung einfügen
    public void addStimmung(StimmungDs Stimmung, SQLiteDatabase connection) {

        int id = getStimmungenCount(connection);
        id++;
        ContentValues values = new ContentValues();
        values.put(Field_Id, id);
        values.put(Field_Tag, Stimmung.getTag());
        values.put(Field_Monat, Stimmung.getMonat());
        values.put(Field_Jahr, Stimmung.getJahr());
        values.put(Field_Zustand, Stimmung.getZustand());
        values.put(Field_Stimmung, Stimmung.getStimmung());
        values.put(Field_Gereitzt, Stimmung.getGereitzt());
        values.put(Field_Text, Stimmung.getText());

        connection.insert(TABLE_NAME, null, values);
        connection.close();
    }
in meiner aufrufenden Class mache ich dann im onCreate
Code:
       database = new DbHandler(this);
       connection = database.getWritableDatabase();
wobei database und connection global deklariert sind (damit ich die in meiner Klasse jederzeit nutzen kann).

und die funktion spreche ich aus meiner aufrufenden Klasse so an
Code:
database.addStimmung(StDs, connection);

irgendwie scheine ich da entweder konzeptionell falsch zu liegen oder wo liegt mein Fehler ?
 
ich gucke mir das mal morgen an bin grad sehr müde und will heia :)
und zu deinem context....eine initialisierung bedeutet nciht dass du den context benutzt
falls du den nur da hast um ihn mit der anweisung zu initialisieren "meckert" eclipse halt rum dass das ne speicherverschwendung wäre und ich sehe laut angegeben code auch keine benutzung von deinem context objekt
 
  • Danke
Reaktionen: zumafx
ok, ich will auch heia, weil augen schon eckig :D

morgen mal sehen, was die kleinen grauen Zellen so über nacht rausfinden ;)

danke für drübergucken schonmal
 
Ich glaub, ich mach da was mit den Klassen/Activity's falsch ?

Mein Gedanke:
Ich hab 3 Activitiy's (Main, Erfassen, Anzeigen). In der Main würde ich gerne meine DB-Klasse erzeugen und diese dann an Erfassen und Anzeigen "durchreichen". Somit würde ich sozusagen bei Start meiner App eine DB (mit den ganzen DB-Methoden) erzeugen und kann die dann innerhalb meiner App in jeder Activity einfach benutzen.
In der DbHandler (s.o.) hätte ich dann gerne alle DB-Sachen und durch einbinden/übergeben an die jeweilige Activity würde ich dann z.b. in der Erfassen-Klasse die Speichernmethoden nutzen, dann die nächste Activity "Anzeigen" aufrufen (wieder die Db-Klasse mit Methoden übergeben) und dort die Lesemethoden benutzen. Die Db soll sozusagen von Start der App bis beenden "leben" und erst bei App-schließen wieder geschlossen werden.
Oder muss ich in jeder meiner Activity's eine Database und Connection erzeugen und dann dort die jeweiligen Methoden (speichern, lesen, usw.) implementieren ?
Ich programmiere normalerweise in Delphi und dort hätte ich dann alle DB-Sachen in einer Unit(=Klasse) und würde die dort einbinden, wo ich sie brauch und kann die dann nach Erzeugen einer Instanz einfach benutzen.
jejeje ... soviele Fragen ...
 
lass die datenbank bei jeder activity auf und zu machen so brauchst du dir kein kopf über sowas amchen...
 
  • Danke
Reaktionen: zumafx
Das Singleton-Muster macht sich imho bei Datenbanken ganz gut. Schaus dir mal an.
 
  • Danke
Reaktionen: zumafx
<klugscheiss>
Und
Code:
private static final String Field_Gereitzt  = "Gereitzt";
solltest Du zu
Code:
private static final String Field_Gereizt  = "Gereizt";
refactoren, ebenso die Methoden dazu.
</klugscheiss>
 
  • Danke
Reaktionen: zumafx
Ich bin dabei, das ganze erstmal umzuschreiben (also Strings in die strings.xml usw.).
Wenn ich euch also richtig verstehe, sollte man in jeder Activity eine connection machen und dann dort die entsprechenden methoden implementieren ?
Na, dann hab ich aber noch einige copy&paste&umschreib-Arbeiten :D
 
und ich stimme renephew zu bei DB's benutzt man das Singleton Muster...es ist ein musteranwendungsbeispiel dieses patterns (bei cs50 in Harvard sagt das auch der Professor...Gang of Four und so ;))
 
Jaiel schrieb:
lass die datenbank bei jeder activity auf und zu machen so brauchst du dir kein kopf über sowas amchen...

Umgebaut und siehe da: funzt :D
 
wunderbar!
 
eine Frage hab ich aber noch :D

wenn ich das richtig verstehe, wird die DB nur beim ersten Start created und falls ich die Versionsnummer erhöhe, dann die update-methode aufgerufen. Wenn diese wiederum die create aufruft und man beispielsweise im update eine 2te tabelle anlegt:
wird die DB komplett neu erstellt (inkl Verlust der Daten) oder wird sozusagen automatisch geprüft, das eine Tabelle schon da ist und dann nur die zweite erstellt ?
hab da nix genaues gefunden, eine quelle zum nachlesen wäre auch nett/ausreichend.
 
zumafx schrieb:
hab da nix genaues gefunden, eine quelle zum nachlesen wäre auch nett/ausreichend.
Was hindert dich daran, dir die generellen Infos zu SQL durchzulesen? z.b. hier: SQL Tutorial

Ist ja nicht androidspezifisch.
 
Ich bin grundsätzlich schon mit SQL vertraut, allerdings habe ich immer nur
mit Interbase gearbeitet bisher. Sqlite und das Zusammenspiel mit Android ist
mir nicht geläufig und meiner Erfahrung nach gibt es je DB-System immer ein
paar Besonderheiten. Sql ist nicht überall 100% gleich.
Aber Frage war eh doof, ich kanns ja einfach ausprobieren ;)
Trotzdem Danke für den Link.
 
Ja stimmt hast schon recht. Aber ich probiere auch immer lieber selber aus, als wenn ich was annehme, wie es eigentlich abläuft und hinterher stellt es sich doch anders heraus. :)
 

Ähnliche Themen

S
Antworten
33
Aufrufe
2.668
Sempervivum
S
S
Antworten
7
Aufrufe
1.158
swa00
swa00
M
Antworten
3
Aufrufe
163
moin
M
Zurück
Oben Unten