关于GreenDao你应该知道的小技巧

【前言】

相信大家在开发中已经使用过GreenDao(What? 还没用过,造起来吧,Now!),
深深地被它的轻量、便捷、迅速、高效这些魅力所吸引了吧。哈哈,本篇博客,
不是要介绍它的使用方式,也不是它的实现原理。没错,就是开发中会遇到的,
关于数据库升级后,如何保证原有数据不丢失。

【背景描述】

假设APP第一个版本,只需要一张表Student,这张表只有两个属性(除了id),name和
age。由于项目需求,要在Student表中增加属性profession,这是就需要在第二个APP
版本中升级数据库版本号。接着项目又有新需求,需增加一张表Teacher,这张表的属性
有name和age(除了id),这时需要在第三个版本的APP中升级数据库版本。
在两次的数据库版本升级中,如果只是简单的drop掉历史table,重新创建表,是可以
做到表的同步更新。但是,历史版本中的数据将会丢失,会造成极差的用户体验。

【关于DaoMaster.DevOpenHelper】

GreenDao默认生成的DaoMaster,它有个静态内部类DevOpenHelper。它的作用是
管理数据库的创建和升级。其中升级的函数onUpgrade实现如下:


@Override
   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
       Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
       dropAllTables(db, true);
       onCreate(db);
   }

可以看出,升级数据库时,GreenDao会调用升级数据库,drop掉所有的历史tables,
然后再重新创建所有的tables,这样就导致了历史数据丢失。

【解决思路】

需要一个数据库升级管理类,如UpgradeManager,代码实现如下:


public class UpgradeManager {

    public static void onUpgrade(SQLiteDatabase db, int oldVersion) {
        switch (oldVersion) {
            case 1:
                /**
                 * Student 表增加字段 PROFESSION
                 */
                db.execSQL("alter table Student add column PROFESSION text");


                /**
                 * 数据库增加表 Teacher
                 */
            case 2:
                TeacherDao.createTable(db, false);


            default:
                break;
        }
    }
}
 

说明:第一次数据库版本的升级需求是,在Student表中增加字段PROFESSION,所以
利用SQL语句的alter来给表Student增加字段。第二次数据库版本的数据需求是,
新增表Teacher,可以用GreenDao封装好的代码来创建表(当然也可以自己写原
生的SQL语句生成)。如果用户用版本2
的APP覆盖安装到版本1的APP,会从case 1开始执行。如果用户是用版本3的APP
覆盖安装了版本2的APP,这时是从case 2开始执行。这样就实现了,既保留了历史
数据,又打到了数据库升级的目的。

注意:这里的case是没有break的。因为,如果加了break,假设用户下载版本3APP
覆盖安装了版本1APP,这时执行case 1,但是没有执行case 2,导致Teacher表
没被创建。还有一个关键点就是,case的顺序必须按照每次升级数据库的需求顺序
添加。比如,第一次的需求是增加Student表字段PROFESSION,第二次需求是新增
表Teacher。

【代码调用】

UpgradeManager的onUpgrade方法是在DevOpenHelper的onUpgrade里面调用的,如下:

 
@Override
   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
       Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
       //dropAllTables(db, true);
       //onCreate(db);
       UpgradeManager.onUpgrade(db, oldVersion);
   }
 

说明:注释掉自动生成的dropAllTables和onCreate,取而代之的实调用UpgradeManager.onUpgrade。
由于每次GreenDao编译自动生成DaoMaster时,都会重新生成onUpgrade,所以
每次数据库版本升级后,要记住执行以上变更的操作(想一劳永逸的话,可以下载
GreenDao的源码,修改dao-master.flt的生成规则即可)

【代码演示】

1、需求变更前
 
public class GeneratorClass {

    public static void main(String[] args) {
        try {

            /**
             * 参数: 版本号 :包名
             */
            Schema schema = new Schema(1, "com.jay.greendao");

            // 对应student表
            Entity student = schema.addEntity("Student");
            student.addIdProperty();
            student.addStringProperty("name").notNull();
            student.addIntProperty("age");

            /**
             * 代码生成路径,需自行设置
             */
            new DaoGenerator().generateAll(schema, "D:\\sources\\GreenDaoDemo\\app\\src\\main\\java-gen");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

注意:此时数据库的版本号为1.

然后,添加一条Student数据到表中:

 
private void insertStudent() {
       StudentDao studentDao = daoSession.getStudentDao();
       Student student = new Student();
       student.setName("jay");
       student.setAge(33);
       studentDao.insert(student);
   }
 

查看表Studen:

2、需求1 —— Student表新增字段PROFESSION
 
public class GeneratorClass {

    public static void main(String[] args) {
        try {

            /**
             * 参数: 版本号 :包名
             */
            Schema schema = new Schema(2, "com.jay.greendao");
            // 对应student表
            Entity student = schema.addEntity("Student");
            student.addIdProperty();
            student.addStringProperty("name").notNull();
            student.addIntProperty("age");
            // 需求一
            student.addStringProperty("profession");
            /**
             * 代码生成路径,需自行设置
             */
            new DaoGenerator().generateAll(schema, "D:\\sources\\GreenDaoDemo\\app\\src\\main\\java-gen");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

说明:此时数据库版本号变更为2,新增了student.addStringProperty(“profession”)。

关键点来了,修改自动生成的DaoMaster.DevOpenHelper的onUpgrade,如下:

 
public static class DevOpenHelper extends OpenHelper {
    public DevOpenHelper(Context context, String name, CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
//            dropAllTables(db, true);
//            onCreate(db);
        UpgradeManager.onUpgrade(db, oldVersion);
    }
}

UpgradeManager的代码如下:

 
public class UpgradeManager {

    public static void onUpgrade(SQLiteDatabase db, int oldVersion) {
        switch (oldVersion) {
            case 1:
                /**
                 * Student 表增加字段 PROFESSION
                 */
                db.execSQL("alter table Student add column PROFESSION text");
            default:
                break;
        }
    }
}
 

说明:此时编译生成版本2的APP,正确的情况是保留了历史数据,并且新增了PROFESSION字段:

3、需求2 —— 新增表Teacher
 
public class GeneratorClass {

    public static void main(String[] args) {
        try {

            /**
             * 参数: 版本号 :包名
             */
            Schema schema = new Schema(3, "com.jay.greendao");
            // 对应student表
            Entity student = schema.addEntity("Student");
            student.addIdProperty();
            student.addStringProperty("name").notNull();
            student.addIntProperty("age");
            // 需求一
            student.addStringProperty("profession");

            // 需求二,新增表Teacher
            Entity teacher = schema.addEntity("Teacher");
            teacher.addIdProperty();
            teacher.addStringProperty("name").notNull();
            teacher.addIntProperty("age");
            /**
             * 代码生成路径,需自行设置
             */
            new DaoGenerator().generateAll(schema, "D:\\sources\\GreenDaoDemo\\app\\src\\main\\java-gen");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

说明:此时数据库版本号为3,新增了表Teacher。

* 别忘了修改自动生成的DaoMaster,修改跟上面的一样。 *
然后插入一条数据到Teacher表,如下:


private void insertTeacher() {
      TeacherDao teacherDao = daoSession.getTeacherDao();
      Teacher teacher = new Teacher();
      teacher.setName("Jom");
      teacher.setAge(22);
      teacherDao.insert(teacher);
  }
 

UpgradeManager的修改如下:


public class UpgradeManager {

    public static void onUpgrade(SQLiteDatabase db, int oldVersion) {
        switch (oldVersion) {
            case 1:
                /**
                 * Student 表增加字段 PROFESSION
                 */
                db.execSQL("alter table Student add column PROFESSION text");

                /**
                 * 数据库增加表 Teacher
                 */
            case 2:
                TeacherDao.createTable(db, false);

            default:
                break;
        }
    }
}

这时,应该保留了历史数据的同时,又新了表Teacher,

【总结】

以上的实现,可以很好的解决数据丢失问题。欢迎大家留言,相互交流学习。有关GreenDao的更多
高级用法,建议访问GreenDao官网

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要配置GreenDao,你需要按照以下步骤进行操作: 1. 在module级别的build.gradle文件中,将以下代码添加到文件的顶部: ``` apply plugin: 'org.greenrobot.greendao' ``` 2. 在同一个build.gradle文件中,添加以下配置到android模块下的greendao块中: ``` greendao { schemaVersion 1 // 设置数据库版本号,升级时可修改 daoPackage 'com.example.greendaodemo.db' // 设置生成的DAO、DaoMaster和DaoSession的包路径,默认与表实体所在的包路径相同 targetGenDir 'src/main/java' // 设置生成的源文件的路径,默认在build目录下的build/generated/source/greendao目录中 } ``` 3. 添加GreenDao的依赖库,将以下代码添加到dependencies块中: ``` implementation 'org.greenrobot:greendao:3.2.2' ``` 这样,你就完成了GreenDao的配置。如果需要生成GreenDao的代码,请确保你还添加了以下依赖库: ``` implementation 'org.greenrobot:greendao-generator:3.2.2' ``` 参考链接:<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [GreenDao的简单配置](https://blog.csdn.net/qq_42061290/article/details/82586342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [GreenDao配置](https://download.csdn.net/download/a511341250/9593713)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [GreenDao配置文档](https://blog.csdn.net/chentaishan/article/details/105263937)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值