Обновление базы данных без потери данных. Неустранимое исключение: ModernAsyncTask # 1 - PullRequest
0 голосов
/ 02 января 2019

Мне нужно реализовать обновление базы данных, лежащей в активах.Пользовательские данные, а именно, в «любимой» записи или нет, должны быть сохранены.

Я уже задавал вопрос, и они мне помогли - https://stackoverflow.com/a/53827525/10261947

Все работало в тестовом приложении.Но когда я перенес код (точно такой же) в реальное приложение, возникает ошибка - E / AndroidRuntime: FATAL EXCEPTION: ModernAsyncTask # 1

 Process: rodionova.lyubov.brodsky, PID: 4196
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:161)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:784)
     Caused by: java.lang.IllegalArgumentException: the bind value at index 4 is null
        at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:169)
        at android.database.sqlite.SQLiteProgram.bindAllArgsAsStrings(SQLiteProgram.java:205)
        at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:47)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1397)
        at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1239)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1110)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1278)
        at rodionova.lyubov.brodsky.db.PoemsDbHelper.insertCorePoem(PoemsDbHelper.java:121)
        at rodionova.lyubov.brodsky.db.PoemsDbHelper.getNewPoems(PoemsDbHelper.java:90)
        at rodionova.lyubov.brodsky.db.PoemsDbHelper.onUpgrade(PoemsDbHelper.java:41)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:197)
        at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getReadableDatabase(SQLiteAssetHelper.java:254)
        at rodionova.lyubov.brodsky.db.PoemsProvider.query(PoemsProvider.java:45)
        at android.content.ContentProvider.query(ContentProvider.java:1057)

Если вы не выполняете обновление, приложениеработает нормально, поэтому выложу только код DbHelper

public class PoemsDbHelper extends SQLiteAssetHelper {
        public static final String DB_NAME = "brodsky.db";
        public static final int DBVERSION = 3;
        public static final String TBLNAME = "poems_table";
        public static final String COL_ID = "id";
        public static final String COL_TITLE = "title";
        public static final String COl_POEM = "poem";
        public static final String COL_SUBJECT = "subject";
        public static final String COL_YEARS = "years";
        public static final String COL_FAVOURITE = "favorite";

        Context mContext;

        public PoemsDbHelper(Context context) {
            super(context, DB_NAME, null, DBVERSION);
            mContext = context;
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if(newVersion > oldVersion)
            getNewPoems(mContext, db);
        }


        private void getNewPoems(Context context, SQLiteDatabase db) {
            InputStream is;
            OutputStream os;
            final String tempNewDbName = "temp_brodsky.db";
            int buffersize = 4096;
            byte[] buffer = new byte[buffersize];
            String newDBPath = mContext.getDatabasePath(tempNewDbName).getPath();


            File newDBFile = new File(newDBPath);
            if (newDBFile.exists()) {
                newDBFile.delete();
            }

            File newDBFileDirectory = newDBFile.getParentFile();
            if (!newDBFileDirectory.exists()) {
                newDBFileDirectory.mkdirs();
            }

            try {
                is = context.getAssets().open("databases/" + DB_NAME);
                os = new FileOutputStream(newDBFile);
                int bytes_read;
                while ((bytes_read = is.read(buffer,0,buffersize)) > 0) {
                    os.write(buffer);
                }
                os.flush();
                os.close();
                is.close();

            }catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("Ouch updated database not copied - processing stopped - see stack-trace above.");
            }

            long id = maxid(db) + 1;
            SQLiteDatabase newdb = SQLiteDatabase.openDatabase(newDBFile.getPath(),null,SQLiteDatabase.OPEN_READONLY);
            Cursor csr = newdb.query(TBLNAME,null,null,null,null,null,null);
            long insert_result;
            db.beginTransaction();
            while (csr.moveToNext()) {
                insert_result = insertCorePoem(
                        db,
                        id,
                        csr.getString(csr.getColumnIndex(COL_TITLE)),
                        csr.getString(csr.getColumnIndex(COl_POEM)),
                        csr.getString(csr.getColumnIndex(COL_SUBJECT)),
                        csr.getString(csr.getColumnIndex(COL_YEARS)),
                        csr.getString(csr.getColumnIndex(COL_FAVOURITE))
                );

                if (insert_result > 0) {
                    id++;
                }

            }
            db.setTransactionSuccessful();
            db.endTransaction();
            csr.close();
            newDBFile.delete();
        }

        public long insertCorePoem(SQLiteDatabase db, long id, String title, String poem, String subject, String years, String favourite) {

            String whereclause = COL_TITLE + "=? AND " + COl_POEM + "=? AND " + COL_SUBJECT + "=? AND " + COL_YEARS + "=?";
            String[] whereargs = new String[]{
                    title,
                    poem,
                    subject,
                    years
            };

            Cursor csr = db.query(TBLNAME,null,whereclause,whereargs,null,null,null);
            boolean rowexists = (csr.getCount() > 0);
            csr.close();
            if (rowexists) {
                Log.d("INSERTCOREPOEM","Skipping insert of row");
                return -2;
            }

            ContentValues cv = new ContentValues();
            cv.put(COL_ID,id);
            cv.put(COL_TITLE,title);
            cv.put(COl_POEM,poem);
            cv.put(COL_SUBJECT,subject);
            cv.put(COL_YEARS,years);
            cv.put(COL_FAVOURITE,favourite);
            Log.d("INSERTCOREPOEM","Inserting new column with id " + String.valueOf(id));
            return db.insert(TBLNAME, null, cv);
        }

        private long maxid(SQLiteDatabase db) {
            long rv = 0;
            String extractcolumn = "maxid";
            String[] col = new String[]{"max(" + COL_ID + ") AS " + extractcolumn};
            Cursor csr = db.query(TBLNAME,col,null,null,null,null,null);
            if (csr.moveToFirst()) {
                rv = csr.getLong(csr.getColumnIndex(extractcolumn));
            }
            csr.close();
            return rv;
        }

    }

Я не понимаю, что не так.Идентичный код работает отлично друг приложение.Буду благодарен за помощь.

1 Ответ

0 голосов
/ 02 января 2019

Ваша проблема заключается в том, что в столбце лет строки или строк в обновленной базе данных, из которой копируются данные, вероятно, есть значение null.

Хотя вы можете изменить код для обработки (пропуститьвставка или использование дают значение года) конечный результат может быть нежелательным.Таким образом, наиболее вероятным решением будет изменить базу данных, чтобы она содержала действительные / полезные значения года.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...