android之orm数据库框架greendao的升级维护

本文介绍了在Android开发中使用ORM框架greendao时遇到的数据库升级问题,包括数据读取的缓存问题以及升级过程中数据丢失的挑战。作者列举了四大升级难题,并详细阐述了解决方案,包括临时表的创建、数据迁移、类型兼容以及表存在性的判断,以确保数据库升级顺利且数据完整。
摘要由CSDN通过智能技术生成

几百年不写博客了,而刚好又一晚上失眠,可能由于刚放完假,还没适应过来吧,反正也睡不着就想着早起写篇文章记录下工作中遇到的一些问题,也顺便静下心,好让自己快速投入工作中。

由于以前做的APP都是小型的,所以对数据库的使用程度不高,一直用自带的手写数据库即可。去年9月份开始加入一个项目的开发,用到了数据库greendao,由于之前没用过,所以做之前查看了相关的资料,但是当做了之后才发现原来坑也挺大。

 greendao由于是orm框架,所以对数据库的操作确实是非常方便的,但是同时也存在一些问题,比如数据的读取,它是有缓存的,你会发现你存了一条数据后再去读取数据,结果并没有你刚插入的那条数据,原因是存在缓存,所以需要清理下缓存,其实这也不算是问题和BUG,应该是设计的初衷是为了一些常规不经常修改的数据,为了读取数据更快才加入的缓存,自己清理下缓存再读取即可。

废话不多说了,重点,每次我们更新数据库之后,比如新增字段、删减字段,需要对数据库的版本号进行增加,这样greendao才知道我们修改了数据库,需要进行数据库的升级,但是问题来了,greendao每次升级数据库都是把本地数据库全部重清空了,表也删了,然后再根据你新版本的表实体来新建新的数据库表,这样就会导致你的数据无法保留,每次一旦有数据库的更新,都会导致数据的丢失,所以网上出现了一些大神写的工具类,实现的思路其实也很简单,首先要屏蔽掉greendao的默认升级功能,然后:

1.首先创建临时表(字段名和属性跟旧表一模一样);

2.遍历所有表,把对应表的数据插入到临时表中;

3.删除原表,新建新表;

4.把临时表数据插入到新表中,然后删除临时表;

以上四个步骤就是网上最公认的数据库升级方式,实现的工具类代码如下:

package com.android.sdongpo.db;

import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import com.android.sdongpo.gen.DaoMaster;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.internal.DaoConfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MigrationHelper {
    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

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

    private static List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }

    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值