android轻量级无侵入式管理数据库自动升级组件

作者:Points 时间:2023-12-09 15:36:01 

SpeSqliteManager4Android

改动日志

2023.2.14 完成SQLiteOpenHelper
2023.2.23 完成room
2023.2.25 完成架构重构
2023.2.26 新增架构设计图说明

介绍

一个轻量级无侵入式管理android数据库自动升级的管理类(支持SQLiteOpenHelper、room)

妈妈再也不用担心写一坨坨的migration或是手动sql去升级数据库

核心设计思想

1.以静制动:配置项代替代码,保证代码稳定性

架构设计

android轻量级无侵入式管理数据库自动升级组件

关配置项json:

  • 1.dbName:数据库文件名称,要保持稳定,不能修改。

  • 2.dbVersion:数据库版本号,判断本地数据库文件是否升级就通过此key,升级时要保证新版本号大于当前的。

  • 3.dbTables:想要创建的表名,每个表名下是具体的字段。

集成步骤

1.导入依赖库

implementation 'com.google.code.gson:gson:2.8.9'
   implementation "androidx.room:room-runtime:2.0.0"
   annotationProcessor "androidx.room:room-compiler:2.0.0"

2.在assets目录下新建dbupdate.json 注意:dbconfig的配置不要动,自己的表在后面新增

3.SQLiteOpenHelper的调用方法

//1.直接创建SQLiteOpenHelper
   SpeSqliteOpenHelperService.getInstance(this);
   //2.创建SQLiteOpenHelper且需要监听db
   SpeSqliteOpenHelperService.getInstance(this, new SpeSqliteBaseInterface() {
     @Override
     public <T> void onCreate(T db, RoomDatabase room) {

}
     @Override
     public <T> void onOpen(T db, RoomDatabase room) {

}
     @Override
     public <T> void onUpgrade(T db, int oldVersion, int newVersion, RoomDatabase room) {

}
   });                                                                                                                                                                                                                                                                                                                                                                      

4.Room的调用方法

//3.直接创建room
       SpeSqliteRoomService.getInstance(this,AppDatabase.class);
   //4.创建room,且需要监听db
       SpeSqliteRoomService.getInstance(this,AppDatabase.class,new SpeSqliteBaseInterface() {
           @Override
           public <T> void onCreate(T db, RoomDatabase room) {
               //TODO  删除测试插入代码
               if(room != null){
                   ServerModel model = new ServerModel();
                   model.setId("1");
                   model.setHost("1");
                   model.setLang("1");
                   model.setName("1");
                   model.setVersion("1");
                   insert(room,model);
               }

}
           @Override
           public <T> void onOpen(T db, RoomDatabase room) {

}

@Override
           public <T> void onUpgrade(T db, int oldVersion, int newVersion, RoomDatabase room) {

}
       });        

核心代码

SpeSqliteUpdateManager 负责针对本地db的创建、新建表、表字段升级、删除表,通过配置的方式去升级数据库,减少代码的改动,核心思想:以静制动

/**
    * 数据库第一次创建时的调用函数
    * @param db db
    */
   public void create(SQLiteDatabase db){
       SpeSqliteSettingModel currentDBModel = SpeSqliteUpdateManager.getInstance().currentAppDBSetting();
       for(int i=0;i<currentDBModel.dbTables.size();i++){
           SpeSqliteTableSettingModel table = currentDBModel.dbTables.get(i);
           String sql = " create table if not exists "+table.tableName+" (";
           for(int j=0;j<table.columns.size();j++){
               SpeSqliteColumnSettingModel column = table.columns.get(j);
               sql+=column.key+" ";
               sql+=column.keyType;
               if(j==table.columns.size()-1){
                   sql+=" ";
               }else {
                   sql+=",";
               }
           }
           sql+=")";
           executeSQL(db,sql);
       }
       //SQLiteDatabase数据库才需要升级本地数据配置
       if(db instanceof SQLiteDatabase){
           SQLiteDatabase _db = (SQLiteDatabase)db;
           updateConfig2DB(_db,currentDBModel);
       }
   }

/**
    * 升级数据库,此处涉及3种改动:1.新建表 2.老表新增字段 3.删除表
    * 注意该方法会被两个数据库依次触发,所以需要控制
    * 1.新建表的处理思路:比较简单直接create即可
    * 2.老表新增字段需要遍历db中的json表字段明细和当前app中的json明细
    * @param db db
    */
   public  void upgrade(SQLiteDatabase configdb,SupportSQLiteDatabase db){
       SpeSqliteSettingModel newConfig = this.currentAppDBSetting();
       SpeSqliteSettingModel localConfig = this.getAppLoclDBSetting(configdb);
       //该处判断可以不要,但是加了后(daupdate.json的dbversion字段)效率更高
       if(localConfig.dbVersion< newConfig.dbVersion){//通过dbversion直接判断是否要升级
           //防止room数据未创建表,就alter
           if(db != null){
               for(int i=0;i<localConfig.dbTables.size();i++) {
                   SpeSqliteTableSettingModel _local = localConfig.dbTables.get(i);
                   createTableSQL(db,_local);
               }
           }
           for(int j=0;j<newConfig.dbTables.size();j++){
               SpeSqliteTableSettingModel _new = newConfig.dbTables.get(j);
               for(int i=0;i<localConfig.dbTables.size();i++){
                   SpeSqliteTableSettingModel _local = localConfig.dbTables.get(i);
                   if(_local.tableName.equals(_new.tableName)){//找到,再判断字段是否有新增
                       _local.indexed = true;//被比较过,该表不用删除
                       if(_local.columns.size()<_new.columns.size()){
                           //执行alert去新增字段 //
                           alterCoulmns(db != null?db:configdb,_local,_new);
                       }
                       break;//只要匹配到就直接跳出该层循环
                   }
               }
               //本地数据没找到这个表需要新增
               createTableSQL(db != null?db:configdb,_new);
           }
           //针对被废弃的表需要在本地库中删除
           for(int i=0;i<localConfig.dbTables.size();i++){
               SpeSqliteTableSettingModel table = localConfig.dbTables.get(i);
               if(!table.indexed){
                   dropTables(db != null?db:configdb,localConfig.dbTables.get(i));
               }
           }
           //只有当是SQLiteDatabase升级时才能本地数据配置
           if(db == null){
               updateConfig2DB(configdb,newConfig);
           }
       }
   }

/**
    * 移除老表
    * @param db db
    * @param table table
    * @param <T> 范型(需考虑SQLiteOpenHelper和room)
    */
   private <T> void dropTables(T db,SpeSqliteTableSettingModel table){
       String sql = " DROP TABLE IF EXISTS "+table.tableName;
       executeSQL(db,sql);
   }

/**
    * 老表新增字段
    * @param db db
    * @param _old 老表字段配置
    * @param _new 表新字段配置
    * @param <T> 范型(需考虑SQLiteOpenHelper和room)
    */
   private <T> void alterCoulmns(T db,SpeSqliteTableSettingModel _old,SpeSqliteTableSettingModel _new){
       for(int i=0;i<_new.columns.size();i++){
           if(i>=_old.columns.size()){
               SpeSqliteColumnSettingModel column = _new.columns.get(i);
               String sql = " alter table "+_old.tableName+" add column ";
               sql+=column.key;
               sql+=" ";
               sql+= column.keyType;
               executeSQL(db,sql);
           }
       }
   }

/**
    * 新增表
    * @param db db
    * @param table 表配置
    * @param <T> 范型(需考虑SQLiteOpenHelper和room)
    */
   private <T> void createTableSQL(T db,SpeSqliteTableSettingModel table){
       String sql = " create table if not exists "+table.tableName+" (";
       for(int j=0;j<table.columns.size();j++){
           SpeSqliteColumnSettingModel column = table.columns.get(j);
           sql+=column.key+" ";
           sql+=column.keyType;
           if(j==table.columns.size()-1){
               sql+=")";
           }else {
               sql+=",";
           }
       }
       executeSQL(db,sql);
   }

运行效果

android轻量级无侵入式管理数据库自动升级组件

项目仓库:gitee.com/hfqf1234/Sp&hellip;

来源:https://juejin.cn/post/7204806134934388797

标签:android,数据库,管理组件,轻量级,无侵入式
0
投稿

猜你喜欢

  • Android仿微信语音聊天功能

    2022-11-24 03:36:12
  • 如何利用反射构建元数据查看器

    2021-05-27 00:11:05
  • Java命令行下Jar包打包小结

    2023-01-04 19:25:44
  • 掌握Android Handler消息机制核心代码

    2023-11-29 18:29:23
  • c# 深拷贝与浅拷贝的区别分析及实例

    2023-06-29 05:00:06
  • 基于SpringBoot多线程@Async的使用体验

    2021-07-15 04:47:04
  • 详解c# 线程同步

    2023-11-23 08:54:48
  • JDK10中的局部变量类型推断var

    2022-06-16 20:32:48
  • 解析SpringBoot整合SpringDataRedis的过程

    2022-07-05 06:45:37
  • C#实现Word和ODT文档相互转换详解

    2022-12-17 21:36:47
  • Android开发中使用外部应用获取SD卡状态的方法

    2023-02-01 21:03:45
  • 使用EasyPoi轻松导入导出Excel文档的方法示例

    2023-12-26 11:47:56
  • C#中的Linq To XML讲解

    2021-06-29 18:39:43
  • 手动编译C#代码的方法

    2021-05-27 05:42:40
  • 新手Hadoop安装 环境搭建

    2022-12-15 05:34:02
  • 基于Android实现点击某个按钮让菜单选项从按钮周围指定位置弹出

    2021-09-13 23:03:40
  • SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

    2023-07-21 19:18:44
  • Java二叉搜索树基础原理与实现方法详解

    2022-09-12 17:20:59
  • Java中Calendar类的一些常用方法小结

    2022-11-21 06:51:06
  • Flutter瀑布流仿写原生的复用机制详解

    2023-06-20 17:02:08
  • asp之家 软件编程 m.aspxhome.com