首页 > 解决方案 > 数据库sqlite。更新不丢失数据

问题描述

有一个包含列的表格:id、title、poe、years、favorite。所以,收藏夹写成 1 或 0,默认为 0,如果用户在收藏夹中添加一行,它就会改变。问题是如果我更新数据库(添加更多行),所有收藏夹都会从用户那里消失。在 SO 的开放空间中,我找到了一个解决方案 - 附加旧的和更新的数据库。我增加了版本,我在项目中添加了一个数据库。在应用程序中,一切都将保持原样。收藏夹被保留,但尚未添加新收藏夹。

 public class PoemsDbHelper extends SQLiteOpenHelper {
        private static String DB_NAME = "brodsky.db";
        private static String DB_PATH = "";
        private static final int DB_VERSION = 8;

        private SQLiteDatabase db;
        private final Context context;
        private boolean needUpdate = false;

        public PoemsDbHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            if (android.os.Build.VERSION.SDK_INT >= 17)
                DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
            else
                DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
            this.context = context;

            copyDataBase();

            this.getReadableDatabase();
        }

        public void updateDataBase() throws IOException {
            if (needUpdate) {
                File dbFile = new File(DB_PATH + DB_NAME);
                if (dbFile.exists()) {
                    //   dbFile.delete();
                    //   copyDataBase();
                    openDataBase();
                    db.execSQL("ATTACH DATABASE '" + DB_PATH + File.separator + DB_NAME + "' AS Old_DB");
                    db.execSQL("INSERT OR IGNORE INTO poems_table (favorite) SELECT id, title, poem, subject, years FROM Old_DB.poems_table;");

                    }
            }
            needUpdate = false;
        }

        private boolean checkDataBase() {
            File dbFile = new File(DB_PATH + DB_NAME);
            return dbFile.exists();
        }

        private void copyDataBase() {
            if (!checkDataBase()) {
                this.getReadableDatabase();
                this.close();
                try {
                    copyDBFile();
                } catch (IOException mIOException) {
                    throw new Error("ErrorCopyingDataBase");
                }
            }
        }

        private void copyDBFile() throws IOException {
            InputStream input = context.getAssets().open(DB_NAME);
            OutputStream output = new FileOutputStream(DB_PATH + DB_NAME);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = input.read(buffer)) > 0)
                output.write(buffer, 0, length);
            output.flush();
            output.close();
            input.close();
        }

        public boolean openDataBase() throws SQLException {
            db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY);
            return db != null;
        }

        @Override
        public synchronized void close() {
            if (db != null)
                db.close();
            super.close();
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (newVersion > oldVersion) {
                needUpdate = true;

          }
       }
    }



 public class PoemsProvider extends ContentProvider {
 @Override
    public boolean onCreate() {
        poemsDbHelper = new PoemsDbHelper(getContext());
        try {
            poemsDbHelper.updateDataBase();
        } catch (IOException mIOException) {
            throw new Error("UnableToUpdateDatabase");
        }

        return true;
    }
}

标签: androidsqliteandroid-sqlite

解决方案


您的问题是您正在覆盖数据库,而不是拥有旧数据库和更新数据库的两个不同副本。基本上,您将数据库附加到自身。

Update DB已经提供了一个解决方案。Sqlite-asset-helper 库

该解决方案使用辅助数据库(从资产文件夹复制更新的数据库)并尝试将更新数据库中的行复制到原始数据库,而不复制(跳过)已经存在的行。应用程序添加的行(与使用外部数据库加载的行相反)保留在原始数据库中。


推荐阅读