SQLite
 sql >> Datenbank >  >> RDS >> SQLite

Aktualisieren einer vorbelegten Datenbank

Laut dem Kommentar von Gabe Sechan wäre die einfachste Methode, die db bei jedem Start der App aus dem Assets-Ordner zu kopieren, dh zu ändern:-

private void createDB(){
    boolean dbExist = DBExists();

    if(!dbExist){
        this.getReadableDatabase();
        copyDBFromResource();

    }
    dbSglite=getReadableDatabase();
}

zu :-

private void createDB(){
    copyDBFromResource();
    dbSglite=getReadableDatabase();
}

Offensichtlich haben Sie Bedenken,

zu kommentieren

"Würde das nicht jedes Mal, wenn eine Aktivität gestartet wird, die DB kopieren."

Ja, das würde es (wäre das so schlimm? - rhetorisch ).

Angenommen, Sie würden die Datenbankversion verwenden, d. h. die Version im Assets-Ordner mit der aktuellen Version vergleichen. Grundsätzlich müssen Sie immer noch über den Assets-Ordner auf die Datenbank zugreifen, also würden Sie eine Datenbank mit einer anderen vergleichen (zumindest öffnen). Es gäbe also noch einige Gemeinkosten.

Eine möglicherweise weniger intensive Option wäre, die zuletzt geänderte Datei der Asset-Datei zu überprüfen date gegen das Datum der zuletzt kopierten Asset-Datei in den gemeinsamen Einstellungen. (File lastModified Methode) Datei - lastModified.

Eine andere Option wäre in einer ähnlichen Ansicht, die Version des Pakets zu überprüfen gegen die zuletzt implementierte, wieder gespeichert in gemeinsamen Einstellungen.PackageInfo - versionCode.

Natürlich erfolgt bei beiden Optionen das Ersetzen der Datenbank aus der Assets-Datei nur, wenn es einen Unterschied (Erhöhung) gibt.

Beispiel mit Paketversion

Das folgende Beispiel (alle Änderungen innerhalb der dbHelper Klasse) kopiert die Datenbank aus den Assets, wenn die Paketversion erhöht wird (oder wenn die Datenbank nicht existiert):-

class dbHelper extends SQLiteOpenHelper {


    private static final String DATABASE_NAME = "questions.db";
    private  static final int SCHEMA_VERSION = 1;
    private static  final String SHARED_PREFS = "shared_prefs";
    private static final String SHARED_PREFKEY_QUESTIONSDBLASTUPDATED = "spkey_qdblastupdated";

    public SQLiteDatabase dbSglite;
    private String mDBPath;

    private final Context myContext;

    public dbHelper(Context context) {
        super(context, DATABASE_NAME, null, SCHEMA_VERSION);
        this.myContext=context;
        this.mDBPath=context.getDatabasePath(DATABASE_NAME).getParent();
    }

    @Override
    public void onCreate(SQLiteDatabase db){
        Log.d("ONCREATE","OnCreate Method Called.");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public void createDatabase(){
        createDB();
    }

    private void createDB(){

        if (isQuestionsDBNew() || (!DBExists())) {
            Log.d("COPYFROMASSET", "Copying Questions From Assets");
            copyDBFromResource();
            setQuestionsDBNew(getPackageVersion());
        } else {
            Log.d("COPYFROMASSET",
                    "Questions not copied from Assets - New Questions Check result was " +
                            Boolean.toString(isQuestionsDBNew()) +
                            " DB Exists result was " + Boolean.toString(DBExists())
            );
        }
        dbSglite=getReadableDatabase();
    }

    private boolean DBExists(){

        SQLiteDatabase db = null;

        try {
            String databasePath = myContext.getDatabasePath(DATABASE_NAME).getPath();
            db = SQLiteDatabase.openDatabase(databasePath,null, SQLiteDatabase.OPEN_READWRITE);
            db.setLocale(Locale.getDefault());
            db.setLockingEnabled(true);
            db.setVersion(1);
        } catch (SQLiteException e) {

            Log.e("SqlHelper", "database not found");
        }

        if (db != null) {
            db.close();
        }
        return db != null;

    }

    private void copyDBFromResource() {
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            inputStream = myContext.getAssets().open(DATABASE_NAME);
            File databasedir = new File(myContext.getDatabasePath(DATABASE_NAME).getParent());
            databasedir.mkdirs();
            outputStream = new FileOutputStream(mDBPath+"/"+DATABASE_NAME);
            byte[] buffer = new byte[1024];
            int length;
            while ((length=inputStream.read(buffer))>0){
                outputStream.write(buffer, 0, length);
            }

            outputStream.flush();
            outputStream.close();
            inputStream.close();

        } catch (IOException e) {
            e.printStackTrace();
            throw new Error("Problem copying database.");
        }

    }

    public void openDataBase() throws SQLException {
        String myPath = myContext.getDatabasePath(DATABASE_NAME).getPath();
        dbSglite = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READWRITE);

    }

    private boolean isQuestionsDBNew() {
        SharedPreferences prefs = myContext.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE);
        long stored_lastused = prefs.getLong(SHARED_PREFKEY_QUESTIONSDBLASTUPDATED,-1);
        Log.d("NEWQUESTIONS?", "Result of testing package version " +
                String.valueOf(stored_lastused) +
                " against " +
                String.valueOf( getPackageVersion()) +
                " was " + String.valueOf(stored_lastused < getPackageVersion()));
        return  (stored_lastused < getPackageVersion());
    }

    private long getPackageVersion() {
        PackageInfo pi;
        try {
            pi = myContext.getPackageManager().getPackageInfo(myContext.getPackageName(),0);
        } catch (PackageManager.NameNotFoundException e) {
            return -1;
        }
        Log.d("PACKAGEVERSION", "The version of package " +
                myContext.getPackageName() +
                " was " +
                String.valueOf(pi.versionCode)
        );
        return pi.versionCode;
    }

    private void setQuestionsDBNew(long lastused) {
        SharedPreferences.Editor editor = myContext.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE).edit();
        editor.putLong(SHARED_PREFKEY_QUESTIONSDBLASTUPDATED,lastused);
        editor.apply();
    }
}

Notizen

  • Der Code basiert stark auf dem Code aus der Frage. Es gibt :-
    • Zwei zusätzliche Klassenvariablen (Konstanten) für die Handhabung gemeinsam genutzter Einstellungen.
    • Drei neue Methoden:-
    • isQuestionsDBNew das gibt true zurück, wenn die Paketversion größer ist als der Versionsspeicher in den gemeinsamen Einstellungen (nichts in den gemeinsamen Einstellungen führt zu -1, sollte also kleiner als jede Paketversion sein).
    • getPackageVersion gibt die Paketversion als long zurück.
    • setQuestionsDBNew wodurch die zutreffende gemeinsame Einstellung aktualisiert wird.
    • Änderungen an createDB, um die Änderung der Paketversion zu überprüfen und dann die Datenbank aus den Assets zu kopieren. Es wird zusätzlich geprüft, ob die Datenbank existiert, was aber nur nötig wäre, wenn nur die Datenbankdatei gelöscht würde. Das Löschen der Daten der App würde die gemeinsamen Einstellungen löschen, was dazu führen würde, dass die Datenbank kopiert wird.
  • Der Code enthält einige Diagnoseprotokolle, die ich gelassen habe.
  • Dies wurde nicht ausgiebig getestet (d.h. ich bin nicht so weit gegangen, die Paketversion zu erhöhen).

Ausgabe aus dem Beispiel – App wird installiert:-

01-05 19:46:44.849 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version -1 against 1 was true
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/COPYFROMASSET: Copying Questions From Assets
01-05 19:46:44.855 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1

Ausgabe aus dem Beispiel - Nachfolgender Lauf :-

01-05 19:48:10.375 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version 1 against 1 was false
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version 1 against 1 was false
01-05 19:48:10.382 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.387 26755-26755/m.com.so48103235_updateprepopdb D/COPYFROMASSET: Questions not copied from Assets - New Questions Check result was false DB Exists result was true
  • Zusätzliche Meldungen aufgrund der ausführlicheren Meldung, die verwendet wird, wenn gemeldet wird, dass die Datenbank nicht kopiert wurde, und erneut Methoden aufruft, die Protokollmeldungen hinzufügen.