j256 / ormlite-android

ORMLite Android functionality used in conjunction with ormlite-core
http://ormlite.com/
ISC License
1.59k stars 366 forks source link

Missing or reset data #117

Open Faltenreich opened 3 years ago

Faltenreich commented 3 years ago

First of all I would like to thank you for OrmLite as it was and is very helpful for migrating my app from using custom cursors to full-fledged object-relational mapping.

Issue Description

Sadly I have some users reporting missing data. These reports come far and few between and so far I was not able to identify common denominators between users. They stretch from several years ago until yesterday when one user reported that some data is going missing sporadically on his Galaxy S9 Dual.

There are no batch tasks that delete data and the only way a DELETE is called is when users delete data manually, one by one. I have checked my CRUD operations and am rather sure that this is some kind of meta-issue affecting OrmLite, the database file or something OS-related. I can only guess wildly since I am not able to reproduce this issue.

Maybe someone has experienced something like that and could help me point in the right direction because I am running out of ideas.

Thank you!

Information

build.gradle

implementation "com.j256.ormlite:ormlite-core:5.1"
implementation "com.j256.ormlite:ormlite-android:5.1"

Initialization

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

    public DatabaseHelper(Context context) {
        super(context, "app.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
        try {
            // Calling for every entity class:
            TableUtils.createTable(connectionSource, <entity class>);
        } catch (SQLException exception) { ... }
    }
}

public class Database {

    private static Database instance;

    public static Database getInstance() {
        if (instance == null) {
            instance = new Database();
        }
        return instance;
    }

    private DatabaseHelper databaseHelper;

    private Database() {}

    public void init(Context context) {
        databaseHelper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
    }

    public DatabaseHelper getDatabaseHelper() {
        return databaseHelper;
    }
}
yuriy-blinov commented 3 years ago

Hi @Faltenreich ,

We have experienced the same issue with database corruptions. When Database corruption is detected, Android's default behaviour is to remove that database completely (see DefaultDatabaseErrorHandler). This behaviour can be overridden if you supply your own implementation of the DatabaseErrorHandler.

To make it possible to provide our own implementation of the DatabaseErrorHandler new constructor has been introduced in the PR #120 .

There are multiple possible reasons for database corruptions see howtocorrupt.

The plan for our APP is to have a daily database backup job running and restoring the last good known database if corruption is detected in our own DatabaseErrorHandler implementation.

Faltenreich commented 3 years ago

Hi @yuriy-blinov,

this sounds frightening!

Thank you for posting your fix which is really interesting. Backing up the whole database on a daily basis seems like a really big step to me. In my scenario, not the whole database is wiped but only a few dataset entries. Maybe this is not the same problem as you experienced?

j256 commented 2 years ago

Any update on this?