Android:onUpgrade之后首次执行getWritableDatabase()时,SQLite“数据库已锁定”异常

问题描述 投票:0回答:1

在我的应用中,我有一个SQLiteHelper类,如下:

class SQLiteHelper extends SQLiteOpenHelper
{
    private static WeakReference<Context> _context; 
    private static final String DATABASE_NAME = "database_name";
    private static final int DATABASE_VERSION = 2;

    SQLiteHelper(Context context)
    {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        _context = new WeakReference<>(context);
    }

    @Override
    public void onCreate(SQLiteDatabase database)
    {
        InputStream is = _context.get().getResources().openRawResource(R.raw.my_database_dump);
        generateSqliteStringBuilder(database, is);
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
    {
        InputStream is = null;

        if (oldVersion < 2)
        {
            is = _context.get().getResources().openRawResource(R.raw.my_database_dump_1_to_2);
        }

        if (is!=null) generateSqliteStringBuilder(database, is);
    }

    private void generateSqliteStringBuilder(SQLiteDatabase database, InputStream is)
    {
        StringBuilder out = new StringBuilder();
        InputStreamReader in = new InputStreamReader(is);
        BufferedReader reader = new BufferedReader(in);

        String line;
        try {
            while ((line = reader.readLine())!=null) out.append(line.replaceAll(";$", ";;"));
            is.close();
            reader.close();
            executeSQLScript(out, database);
        } catch (IOException e) {
            ExceptionHandler.logException(e);
        }
    }

    private void executeSQLScript(StringBuilder out, SQLiteDatabase database)
    {
        try
        {
            String replacedOut = out.toString().trim();
            String[] sql = replacedOut.split(";;");
            for (String statement : sql) {
                if (!statement.contains("android_metadata")) {
                    database.execSQL(statement + ";");
                }
            }
        } catch (Exception e) {
            ExceptionHandler.logException(e);
        }
    }

    public String replace(CharSequence target, CharSequence replacement)
    {
        return Pattern.compile(target.toString(), Pattern.LITERAL)
                .matcher(target).replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }
}

然后我有一个实体-它将使用SQLite存储库-如下所示:

... ENTITY GETTERS AND SETTERS

public static MyEntity1 getMyEntity1(int id, int idLanguage)
{
    MyEntity1 entity1 = null;
    Entity1Repository datasource = new Entity1Repository();

    String strResult = datasource.open();
    if (strResult.equals(Enum.Result.OK)){
        entity1 = datasource.getEntity1(id, idLanguage);
    }
    datasource.close();

    return entity1;
}

... MORE REPOSITORY METHODS

而且我终于有了一个Entity1存储库,如下所示:

public class Entity1Repository {

    private SQLiteDatabase database;

    public Entity1Repository() {

        dbHelper = new SQLiteHelper(AppSettings.getContext());
    }

    public String open() {

        String strResult = Enum.Result.OK;

        try {
            database = dbHelper.getWritableDatabase();
        } catch (Exception e) {
            strResult = Enum.Result.KO;
            ExceptionHandler.logException(e);
        }

        return strResult;
    }

    public void close() {
        dbHelper.close();
    }

    public Entity1 getEntity1(int id, int idLanguage) {

        Entity1 entity1 = null;
        String strWhere = SQLiteHelper.TABLE_ENTITY1_COLUMN_ID + "= ? AND " +
                SQLiteHelper.TABLE_ENTITY1_COLUMN_IDLANGUAGE + "= ?";

        Cursor cursor = database.query(SQLiteHelper.TABLE_ENTITY1,
                allColumns, strWhere, new String[] {String.valueOf(id), String.valueOf(idLanguage)}, null, null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            entity1 = cursorToEntity1(cursor);
            cursor.moveToNext();
        }
        cursor.close();
        return entity1;
    }

    ...
}

SQLite 1_to_2转储文件:

BEGIN TRANSACTION;

...
INSERTS
...

COMMIT;

并且直到现在我必须更新数据库版本,一切都工作正常。我已将DATABASE_VERSION从1增加到2,并在将要执行下一个“数据库= dbHelper.getWritableDatabase()”时调用onUpgrade之后,将引发“数据库锁定”异常。

经过几个小时的调试,我完全被卡住了。

android database sqlite sqliteopenhelper
1个回答
0
投票

[onCreate()onUpgrade()已经在事务中执行,而sqlite并不真正支持嵌套事务。

从您的SQL脚本中删除BEGIN TRANSACTIONCOMMIT

© www.soinside.com 2019 - 2024. All rights reserved.