GreenDao

作者: 夜沐下的星雨 | 来源:发表于2020-06-11 16:44 被阅读0次

    数据库:MySQL、Oracle、Sqlite

    一. 复习SQL语句(结构化查询语言)

    1.SQL语句分类

    • DDL数据定义语言

    用于创建、修改、和删除数据库内的数据结构,如:
    1.创建和删除数据库(CREATE DATABASE || DROP DATABASE);
    2.创建、修改、重命名、删除表(CREATE TABLE || ALTER TABLE|| RENAME TABLE||DROP TABLE);
    3.创建和删除索引(CREATEINDEX || DROP INDEX)

    • DML数据操作语言

    修改数据库中的数据,包括插入(INSERT)、更新(UPDATE)和删除(DELETE)

    • DCL数据控制语言

    用于对数据库的访问,如:1:给用户授予访问权限(GRANT);2:取消用户访问权限(REMOKE)

    • DQL数据查询语言

    从数据库中的一个或多个表中查询数据(SELECT)

    2.SQL语句

    • (1)库

    create database aaa; //创建数据库
    drop database aaa; //删除数据库
    use aaa; //切换使用数据库
    show databases; //显示数据库

    • (2)表

    create table abc(name text,sex varchar(100),age int(10));//创建表结构
    drop table abc; //删除表
    desc abc; //显示表结构

    • (3)数据

    insert into abc(name,sex,age) values('abc','nan',20); //插入数据
    update abc set age = 101 【where name = 'abc'】 //更改数据
    delete from abc 【where name = 'abc'】 //删除数据
    select * from abc 【where age > 18】 //查询数据

    • (4)约束

    主键: primary key
    自增: auto_increment
    非空: not null
    唯一: unique

    create table abc(
        id  int primary key auto_increment,    主键自增
        name varchar not null unique,           非空唯一
        sex varchar,
    );
    
    
    • (5)查询
      一、基本查询
    select * from emp;
    select empno,ename,sal from emp;
    select distinct deptno from emp;    
    select sal*1.5 from emp;
    select concat('$',sal) from emp;
    select concat(sal,'RMB') from emp;
    select ifnull(comm,0)+1000 from emp;
    select sal as 奖金 from emp;
    
    

    二、条件查询

            select * from emp where deptno = 20;
            select * from emp where deptno != 20;
            select * from emp where sal >=20000;
            select * from emp where sal >=10000 and sal <=20000;
            select * from emp where sal<=10000 or sal >=40000;
            select * from emp where comm is null;
            select * from emp where comm is not null;
            select * from emp where sal between 20000 and 40000;
            select * from emp where deptno in(10,30);
    
    

    三、模糊查询 _某一个字符 %多个字符

            select * from emp where ename like '张_';
            select * from emp where ename like '张%';
            select * from emp where ename like '_一_';
    
    

    四、排序

            select * from emp order by sal asc;
            select * from emp order by sal desc;
    
    

    五、聚合函数

            select max(sal) from emp;
            select min(sal) from emp;
            select count(ename) from emp;
            select sum(sal) from emp;
            select avg(sal) from emp;
    
    

    六、分组
    select deptno,count(ename) from emp group by deptno;

    总结:

    select deptno,count(ename)
            from emp
            where sal >= 10000
            group by deptno
            order by deptno asc;
    
    

    二.复习SQLliteDatabase

    SQLiteDatabase的创建和实现的方法
    SQLiteOpenHelper的使用
    onCreate的调用机制,onUpgrade的调用机制;建库、建表
    增删改查(使用sql语句方式)
    增删改查(使用系统方法)

    三.GreenDao的概述以及特点

    • 概述
      ①基于对象关系的映射方式来操作数据库的框架,提供一个接口通过操作对象的方式操作数据库
      ② 适用于 Android 的ORM 框架,现在市面上主流的框架有 OrmLite、SugarORM、Active Android、Realm 与 GreenDAO。
      ③GreenDAO是一种Android数据库ORM(对象映射关系(Object Relation Mapping))框架,与OrmLite、ActiveOrm、LitePal等数据库相比,单位时间内可以插入、更新和查询更多的数据,而且提供了大量的灵活通用接口。
    • 特点
      ①通常我们在使用GreenDao的时候,我们只需定义数据模型,GreenDao框架将创建数据对象(实体)和DAO(数据访问对象),能够节省部分代码。
      ②不向性能妥协,使用了GreenDao,大多数实体可以以每秒几千个实体的速率进行插入,更新和加载。
      ③GreenDao支持加密数据库来保护敏感数据。
      ④微小的依赖库,GreenDao的关键依赖库大小不超过100kb.
      ⑤如果需要,实体是可以被激活的。而活动实体可以透明的解析关系(我们要做的只是调用getter即可),并且有更新、删除和刷新方法,以便访问持久性功能。
      ⑥GreenDao允许您将协议缓冲区(protobuf)对象直接保存到数据库中。如果您通过protobuf通话到您的服务器,则不需要另一个映射。常规实体的所有持久性操作都可以用于protobuf对象。所以,相信这是GreenDao的独特之处。
      ⑦自动生成代码,我们无需关注实体类以及Dao,因为GreenDao已经帮我们生成了。
      ⑧开源 有兴趣的同学可以查看源码,深入去了解机制。

    四.GreenDao配置依赖

    1. 工程配置:添加插件 更好支持GreenDao
    buildscript {
        repositories {
        jcenter()
        mavenCentral() // 添加的代码
         }
        dependencies {
         classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
                }
    }
    
    
    1. 项目配置:添加插件
    apply plugin: 'com.android.application'
    apply plugin: 'org.greenrobot.greendao' // apply plugin
    
    
    1. 项目配置:添加依赖
    dependencies {
    //greendao
    implementation 'org.greenrobot:greendao:3.2.2' // add library
    }
    
    
    1. 初始化GreenDao配置
    greendao{
        schemaVersion 1 //数据库版本号
        daoPackage 'com.example.lizhengjun.dao'  //数据库全路径
        targetGenDir 'src/main/java'  //存放位置
     }
    
    schemaVersion--> 指定数据库schema版本号,迁移等操作会用到;
    daoPackage --> dao的包名,包名默认是entity所在的包;
    targetGenDir --> 生成数据库文件的目录;
    
    

    五.GreenDao的使用思路

    1. 配置文件中的设置
    2. 设置Green中的DaoMaster/DaoSession/实体类Dao生成路径
    3. 设置实体类
        @Entity
        public class Student {
    
            @Id(autoincrement = true)
            private Long id;
    
            @Property
            @NotNull
            private String name;
    
            @Property
            private int age;
        }
    
    
    1. 文件生成:Build - > ReBuild Project

    2. 在Application类中完成内容配置(或者使用工具类)

      Application有自己的生命周期,OnCreate方法必须首先被调用
      ①本类对象的获取
      ②DaoMaster、DaoSession对象的获取
      ③提供方法,获取DaoSession对象

      需要注意:必须在AndroidManifest.xml文件完成配置
      <application
      android:name=".App">
      </application>

    3. 获取实体类Dao对象
      XXXDao xxxdao = App.getInstance().getDaoSession().getXXXDao();
      xxxdao.增删改查();

    六.GreenDao注解

    @Entity   标识实体类,greenDAO会映射成sqlite的一个表,表名为实体类名的大写形式
    @Id 标识主键,该字段的类型为long或Long类型,autoincrement设置是否自动增长
    @Property       标识该属性在表中对应的列名称, nameInDb设置名称
    @Transient      标识该属性将不会映射到表中,也就是没有这列
    @NotNull         设置表中当前列的值不可为空
    @Convert         指定自定义类型(@linkPropertyConverter)
    @Generated 运行所产生的构造函数或者方法,被此标注的代码可以变更或者下次运行时清除
    @Index    使用@Index作为一个属性来创建一个索引;
    @JoinEntity     定义表连接关系
    @JoinProperty         定义名称和引用名称属性关系
    @Keep     注解的代码段在GreenDao下次运行时保持不变
    @OrderBy        指定排序方式
    @ToMany         定义与多个实体对象的关系
    @ToOne  定义与另一个实体(一个实体对象)的关系
    @Unique 向数据库列添加了一个唯一的约束
    
    /**
     * @Entity
     * @Id(autoincrement = true)  标志主键
     * @NotNull 标志这个字段不能是null
     * @Property(nameInDb = "User")
     * @Transient 表示不存储在数据库中
     * @Index(unique = true)
     * @Unique 用于标志列的值的唯一性。
     */
    
    

    七.GreenDao对外提供的核心类简介

    1,DaoMaster
    DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的Dao类。它具有静态方法来创建表或将他们删除。其内部类OpenHelper和DevOpenHelper是在SQLite数据库中创建模式的SQLiteOpenHelper实现。
    
    2,DaoSession
    管理特定模式的所有可用Dao对象,您可以使用其中一个getter方法获取。DaoSession还为实体提供了一些通用的持久性方法,如插入,加载,更新,刷新和删除。最后,DaoSession对象也跟踪一个身份范围。
    
    3,XXXDao层
    数据访问对象(Dao)持续存在并查询实体。对于每个实体,GreenDao生成一个Dao,它比DaoSession有更多的持久化方法,例如:count,loadAll和insertInTx。
    
    4,实体
    持久对象,通常实体是使用标准Java属性(如POJO或JavaBean)来表示数据库的对象。
    
    1、DevOpenHelper:创建SQLite数据库的SQLiteOpenHelper的具体实现。 
    2、DaoMaster:GreenDao的顶级对象,作为数据库对象、用于创建表和删除表。 
    3、DaoSession:管理所有的Dao对象,Dao对象中存在着增删改查等API。
    
    

    八.GreenDao使用

    1.核心使用步骤

    //1.创建数据库
    DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(MyApp.getMyApp(), "student.db");
    
    //2.获取读写对象
    DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
    
    //3.获取管理器类
    DaoSession daoSession = daoMaster.newSession();
    
    //4.获取表对象
     studentDao = daoSession.getStudentDao();
    
    daoSession.clear();  清除整个session,没有缓存对象返回
    
    

    2.完整使用步骤(Application)

    public class App extends Application {
    
        private StudentDao studentDao;//Dao操作类
    
        private static App app;
    
        public static App getInstance() {
            return app;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            //本类对象
            app = this;
    
            //创建数据库以及创建数据表
            createDataBase();
        }
    
        private void createDataBase() {
            //1.创建数据库
            DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "student.db");
    
            //2.获取读写对象
            DaoMaster daoMaster = new DaoMaster(helper.getWritableDatabase());
    
            //3.获取管理器类
            DaoSession daoSession = daoMaster.newSession();
    
            //4.获取表对象
            studentDao = daoSession.getStudentDao();
        }
    
        public StudentDao getStudentDao() {
            return studentDao;
        }
    }
    
    

    2.完整使用步骤(工具类)

    • 提供全局上下文
    public class GreenDaoApplication extends Application {
        private static GreenDaoApplication app;
    
        @Override
        public void onCreate() {
            super.onCreate();
            app = this;
        }
    
        public static GreenDaoApplication getApp() {
            return app;
        }
    }
    
    
    • 注册application
        <application
            android:name=".GreenDaoApplication"
            ...>
    
        </application>
    
    
    • 数据库工具类
    public class DbHelper {
        private final StudentBeanDao studentBeanDao;
        private static volatile DbHelper instance;
    
        public static DbHelper getInstance() {
            if (instance == null) {
                synchronized (DbHelper.class) {
                    if (instance == null) {
                        instance = new DbHelper();
                    }
                }
            }
            return instance;
        }
    
        private DbHelper() {
            //创建数据库
            //DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(GreenDaoApplication.getApp(), "student.db");
            GreenDaoHelper devOpenHelper = new GreenDaoHelper(GreenDaoApplication.getApp(), "student.db");
    
            //获取读写对象
            DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
    
            //获取管理器
            DaoSession daoSession = daoMaster.newSession();
    
            //获取表对象
            studentBeanDao = daoSession.getStudentBeanDao();
        }
    
         /**
         * 判断表中是否应有了该对象
         *
         * @param studentBean
         * @return
         */
        private boolean isHased(StudentBean studentBean) {
            List<StudentBean> list = studentBeanDao.queryBuilder().where(StudentBeanDao.Properties.Title.eq(studentBean.getTitle())).list();
            if (list.size() > 0) {
                return true;
            } else {
                return false;
            }
        }
    
        /**
         * 插入数据
         *
         * @param studentBean
         * @return
         */
        public long insert(StudentBean studentBean) {
            if (!isHased(studentBean)) {
                long l = studentBeanDao.insertOrReplace(studentBean);
                return l;
            }
            return -1;
        }
    
        /**
         * 删除数据
         *
         * @param studentBean
         * @return
         */
        public boolean delete(StudentBean studentBean) {
            if (isHased(studentBean)) {
                studentBeanDao.delete(studentBean);
                return true;
            }
            return false;
        }
    
        /**
         * 查询全部
         *
         * @return
         */
        public List<StudentBean> queryAll() {
            List<StudentBean> studentBeans = studentBeanDao.loadAll();
            List<StudentBean> list = studentBeanDao.queryBuilder().list();
            return list;
        }
    
        /**
         * 查询固定名字
         *
         * @param name
         * @return
         */
        public List<StudentBean> queryByName(String name) {
            return studentBeanDao.queryBuilder().where(StudentBeanDao.Properties.Name.eq(name)).list();
        }
    
        /**
         * 查询固定名字和年龄的
         *
         * @param student
         * @return
         */
        public List<StudentBean> queryStudent(StudentBean student) {
            return studentBeanDao.queryBuilder().where(StudentBeanDao.Properties.Name.eq(student.getName()), StudentBeanDao.Properties.Age.gt(student.getAge())).list();
        }
    
        /**
         * 查询第几页的多少条数据
         *
         * @param page
         * @param count
         * @return
         */
        public List<StudentBean> queryPage(int page, int count) {
            return studentBeanDao.queryBuilder().offset(page * count).limit(count).list();
        }
    
        /**
         * @param studentDao
         * @return
         */
        public StudentBean query(StudentBean studentDao) {
            StudentBean student = studentBeanDao.queryBuilder().where(StudentBeanDao.Properties.Id.eq(studentDao.getId())).build().unique();
            return student;
        }
    
        /**
         * 修改
         *
         * @param studentBean
         */
        public void updata(StudentBean studentBean) {
           if (isHased(studentBean)) {
                studentBeanDao.update(studentBean);
                return true;
            }
            return false;
        }
    }
    
    

    九.GreenDao数据库升级

    1. 升级背景
      在版本迭代时,我们经常需要对数据库进行升级,而GreenDAO默认的DaoMaster.DevOpenHelper在进行数据升级时,会把旧表删除,然后创建新表,并没有迁移旧数据到新表中,从而造成数据丢失。
      这在实际中是不可取的,因此我们需要作出调整。下面介绍数据库升级的步骤与要点。

    2. 升级原理
      ①创建一张新表
      ②旧表数据拷贝一份到新表
      注意:没有的数据给默认数据,修改、新加的字段必须为包装类
      ③删除旧表

    3. 升级步骤

    public class MigrationHelper {
        public static boolean DEBUG = false;
        private static String TAG = "MigrationHelper";
        private static final String SQLITE_MASTER = "sqlite_master";
        private static final String SQLITE_TEMP_MASTER = "sqlite_temp_master";
    
        private static WeakReference<ReCreateAllTableListener> weakListener;
    
        public interface ReCreateAllTableListener{
            void onCreateAllTables(Database db, boolean ifNotExists);
            void onDropAllTables(Database db, boolean ifExists);
        }
    
        public static void migrate(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            printLog("【The Old Database Version】" + db.getVersion());
            Database database = new StandardDatabase(db);
            migrate(database, daoClasses);
        }
    
        public static void migrate(SQLiteDatabase db, ReCreateAllTableListener listener, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            weakListener = new WeakReference<>(listener);
            migrate(db, daoClasses);
        }
    
        public static void migrate(Database database, ReCreateAllTableListener listener, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            weakListener = new WeakReference<>(listener);
            migrate(database, daoClasses);
        }
    
        public static void migrate(Database database, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            printLog("【Generate temp table】start");
            generateTempTables(database, daoClasses);
            printLog("【Generate temp table】complete");
    
            ReCreateAllTableListener listener = null;
            if (weakListener != null) {
                listener = weakListener.get();
            }
    
            if (listener != null) {
                listener.onDropAllTables(database, true);
                printLog("【Drop all table by listener】");
                listener.onCreateAllTables(database, false);
                printLog("【Create all table by listener】");
            } else {
                dropAllTables(database, true, daoClasses);
                createAllTables(database, false, daoClasses);
            }
            printLog("【Restore data】start");
            restoreData(database, daoClasses);
            printLog("【Restore data】complete");
        }
    
        private static void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            for (int i = 0; i < daoClasses.length; i++) {
                String tempTableName = null;
    
                DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
                String tableName = daoConfig.tablename;
                if (!isTableExists(db, false, tableName)) {
                    printLog("【New Table】" + tableName);
                    continue;
                }
                try {
                    tempTableName = daoConfig.tablename.concat("_TEMP");
                    StringBuilder dropTableStringBuilder = new StringBuilder();
                    dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";");
                    db.execSQL(dropTableStringBuilder.toString());
    
                    StringBuilder insertTableStringBuilder = new StringBuilder();
                    insertTableStringBuilder.append("CREATE TEMPORARY TABLE ").append(tempTableName);
                    insertTableStringBuilder.append(" AS SELECT * FROM `").append(tableName).append("`;");
                    db.execSQL(insertTableStringBuilder.toString());
                    printLog("【Table】" + tableName +"\n ---Columns-->"+getColumnsStr(daoConfig));
                    printLog("【Generate temp table】" + tempTableName);
                } catch (SQLException e) {
                    Log.e(TAG, "【Failed to generate temp table】" + tempTableName, e);
                }
            }
        }
    
        private static boolean isTableExists(Database db, boolean isTemp, String tableName) {
            if (db == null || TextUtils.isEmpty(tableName)) {
                return false;
            }
            String dbName = isTemp ? SQLITE_TEMP_MASTER : SQLITE_MASTER;
            String sql = "SELECT COUNT(*) FROM `" + dbName + "` WHERE type = ? AND name = ?";
            Cursor cursor=null;
            int count = 0;
            try {
                cursor = db.rawQuery(sql, new String[]{"table", tableName});
                if (cursor == null || !cursor.moveToFirst()) {
                    return false;
                }
                count = cursor.getInt(0);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return count > 0;
        }
    
        private static String getColumnsStr(DaoConfig daoConfig) {
            if (daoConfig == null) {
                return "no columns";
            }
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < daoConfig.allColumns.length; i++) {
                builder.append(daoConfig.allColumns[i]);
                builder.append(",");
            }
            if (builder.length() > 0) {
                builder.deleteCharAt(builder.length() - 1);
            }
            return builder.toString();
        }
    
        private static void dropAllTables(Database db, boolean ifExists, @NonNull Class<? extends AbstractDao<?, ?>>... daoClasses) {
            reflectMethod(db, "dropTable", ifExists, daoClasses);
            printLog("【Drop all table by reflect】");
        }
    
        private static void createAllTables(Database db, boolean ifNotExists, @NonNull Class<? extends AbstractDao<?, ?>>... daoClasses) {
            reflectMethod(db, "createTable", ifNotExists, daoClasses);
            printLog("【Create all table by reflect】");
        }
    
        /**
         * dao class already define the sql exec method, so just invoke it
         */
        private static void reflectMethod(Database db, String methodName, boolean isExists, @NonNull Class<? extends AbstractDao<?, ?>>... daoClasses) {
            if (daoClasses.length < 1) {
                return;
            }
            try {
                for (Class cls : daoClasses) {
                    Method method = cls.getDeclaredMethod(methodName, Database.class, boolean.class);
                    method.invoke(null, db, isExists);
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        private static void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            for (int i = 0; i < daoClasses.length; i++) {
                DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
                String tableName = daoConfig.tablename;
                String tempTableName = daoConfig.tablename.concat("_TEMP");
    
                if (!isTableExists(db, true, tempTableName)) {
                    continue;
                }
    
                try {
                    // get all columns from tempTable, take careful to use the columns list
                    List<TableInfo> newTableInfos = TableInfo.getTableInfo(db, tableName);
                    List<TableInfo> tempTableInfos = TableInfo.getTableInfo(db, tempTableName);
                    ArrayList<String> selectColumns = new ArrayList<>(newTableInfos.size());
                    ArrayList<String> intoColumns = new ArrayList<>(newTableInfos.size());
                    for (TableInfo tableInfo : tempTableInfos) {
                        if (newTableInfos.contains(tableInfo)) {
                            String column = '`' + tableInfo.name + '`';
                            intoColumns.add(column);
                            selectColumns.add(column);
                        }
                    }
                    // NOT NULL columns list
                    for (TableInfo tableInfo : newTableInfos) {
                        if (tableInfo.notnull && !tempTableInfos.contains(tableInfo)) {
                            String column = '`' + tableInfo.name + '`';
                            intoColumns.add(column);
    
                            String value;
                            if (tableInfo.dfltValue != null) {
                                value = "'" + tableInfo.dfltValue + "' AS ";
                            } else {
                                value = "'' AS ";
                            }
                            selectColumns.add(value + column);
                        }
                    }
    
                    if (intoColumns.size() != 0) {
                        StringBuilder insertTableStringBuilder = new StringBuilder();
                        insertTableStringBuilder.append("REPLACE INTO `").append(tableName).append("` (");
                        insertTableStringBuilder.append(TextUtils.join(",", intoColumns));
                        insertTableStringBuilder.append(") SELECT ");
                        insertTableStringBuilder.append(TextUtils.join(",", selectColumns));
                        insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
                        db.execSQL(insertTableStringBuilder.toString());
                        printLog("【Restore data】 to " + tableName);
                    }
                    StringBuilder dropTableStringBuilder = new StringBuilder();
                    dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
                    db.execSQL(dropTableStringBuilder.toString());
                    printLog("【Drop temp table】" + tempTableName);
                } catch (SQLException e) {
                    Log.e(TAG, "【Failed to restore data from temp table 】" + tempTableName, e);
                }
            }
        }
    
        private static List<String> getColumns(Database db, String tableName) {
            List<String> columns = null;
            Cursor cursor = null;
            try {
                cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 0", null);
                if (null != cursor && cursor.getColumnCount() > 0) {
                    columns = Arrays.asList(cursor.getColumnNames());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null)
                    cursor.close();
                if (null == columns)
                    columns = new ArrayList<>();
            }
            return columns;
        }
    
        private static void printLog(String info){
            if(DEBUG){
                Log.d(TAG, info);
            }
        }
    
        private static class TableInfo {
            int cid;
            String name;
            String type;
            boolean notnull;
            String dfltValue;
            boolean pk;
    
            @Override
            public boolean equals(Object o) {
                return this == o
                        || o != null
                        && getClass() == o.getClass()
                        && name.equals(((TableInfo) o).name);
            }
    
            @Override
            public String toString() {
                return "TableInfo{" +
                        "cid=" + cid +
                        ", name='" + name + '\'' +
                        ", type='" + type + '\'' +
                        ", notnull=" + notnull +
                        ", dfltValue='" + dfltValue + '\'' +
                        ", pk=" + pk +
                        '}';
            }
    
            private static List<TableInfo> getTableInfo(Database db, String tableName) {
                String sql = "PRAGMA table_info(`" + tableName + "`)";
                printLog(sql);
                Cursor cursor = db.rawQuery(sql, null);
                if (cursor == null)
                    return new ArrayList<>();
    
                TableInfo tableInfo;
                List<TableInfo> tableInfos = new ArrayList<>();
                while (cursor.moveToNext()) {
                    tableInfo = new TableInfo();
                    tableInfo.cid = cursor.getInt(0);
                    tableInfo.name = cursor.getString(1);
                    tableInfo.type = cursor.getString(2);
                    tableInfo.notnull = cursor.getInt(3) == 1;
                    tableInfo.dfltValue = cursor.getString(4);
                    tableInfo.pk = cursor.getInt(5) == 1;
                    tableInfos.add(tableInfo);
                    // printLog(tableName + ":" + tableInfo);
                }
                cursor.close();
                return tableInfos;
            }
        }
    }
    
    
    • 第二步:
      新建一个类,继承DaoMaster.DevOpenHelper,重写onUpgrade(Database db, int oldVersion, int newVersion)方法,在该方法中使用MigrationHelper进行数据库升级以及数据迁移。
    public class MyOpenHelper extends DaoMaster.OpenHelper {
        public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
            super(context, name, factory);
        }
    
        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
    
            //把需要管理的数据库表DAO作为最后一个参数传入到方法中
            MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
    
                @Override
                public void onCreateAllTables(Database db, boolean ifNotExists) {
                    DaoMaster.createAllTables(db, ifNotExists);
                }
    
                @Override
                public void onDropAllTables(Database db, boolean ifExists) {
                    DaoMaster.dropAllTables(db, ifExists);
                }
            },  BeanDao.class);
        }
    }
    
    

    然后使用MyOpenHelper替代DaoMaster.DevOpenHelper来进行创建数据库等操作

    mSQLiteOpenHelper = new MyOpenHelper(MyApplication.getInstance(), DB_NAME, null);//建库
    mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
    mDaoSession = mDaoMaster.newSession();
    
    
    • 第三步:
      ①在表实体中,调整其中的变量(表字段),一般就是新增/删除/修改字段。
      ②将原本自动生成的构造方法以及getter/setter方法删除,重新Build—>Make Project进行生成。
      注意:
      ①新增的字段或修改的字段,其变量类型应使用基础数据类型的包装类,如使用Integer而不是int,避免升级过程中报错。
      ①根据MigrationHelper中的代码,升级后,新增的字段和修改的字段,都会默认被赋予null值。

    • 第四步:
      修改Module下build.gradle中数据库的版本号schemaVersion ,递增加1即可,最后运行app

    greendao {
        //数据库版本号,升级时进行修改
        schemaVersion 2
    
        daoPackage 'com.dev.base.model.db'
        targetGenDir 'src/main/java'
    }
    

    相关文章

      网友评论

        本文标题:GreenDao

        本文链接:https://www.haomeiwen.com/subject/ubnbtktx.html