美文网首页数据缓存dao程序员
greenDAO3 入门(配置,基本操作,数据库升级)

greenDAO3 入门(配置,基本操作,数据库升级)

作者: david_zhw | 来源:发表于2017-01-06 17:40 被阅读7569次
    Sqlite作为android重要的数据存储库,原生类SQLiteOpenHelper使用起来繁琐容易出错,本着"偷懒"的目的,来学习一下当下十分受欢迎的ORM 框架: greenDAO;网上教程不少,但是大都是针对3.0之前的版本,greenDAO2和3的构建和生成代码的方式区别很大,最终还是通过greenDAO github上的介绍,慢慢摸索,成功的在项目中构建了greenDAO,本文章写于greenDao更新至3.2版本

    一、什么是greenDAO?

    官方介绍:
    greenDAO github
    greenDAO 官网
    网友的博客:
    Android ORM框架 GreenDao3.0的使用

    greenDAO3开始使用注解的方式定义实体类(entity),并且是通过安装gradle插件来生成代码。

    二、如何使用greenDAO

    构建之前,不熟悉gradle概念的同学建议学习Gradle for android 系列教程

    先来看下greenDAO 官方构建介绍:

    greenDAO github 构建介绍
    开始搭建:
    • github中提示添加maven仓库,但是android studio 项目已经默认包含了jcenter仓库,而jcenter仓库就是maven仓库的一个分支,因此我们不要再添加仓库,直接添加classPath即可
    项目下build.gradle
    • 在moudle下的build.gradle文件中 申明插件以及配置greendao(可以不配置)
    moudle 下build.gradle脚本中配置
    • 并在dependencies中添加compile
      /* green dao */
      compile 'org.greenrobot:greendao:3.2.0
    

    三、使用greenDAO

    1. 编写实体类:User类,使用greendao @Entity注解
    import org.greenrobot.greendao.annotation.Entity;
    import org.greenrobot.greendao.annotation.Id;
    @Entity
    public class User {
        @Id
        private long id;
        private String userName;
        private int age;
        private String gender;
    }
    
    1. 编译项目,build后greendao插件会为所有带有该注解的实体生成Dao文件,以及DaoManager与DaoSession,默认生成目录为build/generated/source ,如果我们在gradle脚本中配置了,则会生成在我们的配置目录
    在配置目录中生成dao文件

    不配置,则在默认目录(build/generated/source/greendao)下生成dao文件:

    不配置,则在默认目录下生成dao文件

    四、greenDAO 注解

    1.实体@Entity注解
    
    schema:告知GreenDao当前实体属于哪个schema
    active:标记一个实体处于活动状态,活动实体有更新、删除和刷新方法
    nameInDb:在数据中使用的别名,默认使用的是实体的类名
    indexes:定义索引,可以跨越多个列
    createInDb:标记创建数据库表
    2.基础属性注解
    
    @Id :主键 Long型,可以通过@Id(autoincrement = true)设置自增长
    @Property:设置一个非默认关系映射所对应的列名,默认是的使用字段名 举例:@Property (nameInDb="name")
    @NotNul:设置数据库表当前列不能为空
    @Transient :添加次标记之后不会生成数据库表的列
    3.索引注解
    
    @Index:使用@Index作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束
    @Unique:向数据库列添加了一个唯一的约束
    4.关系注解
    
    @ToOne:定义与另一个实体(一个实体对象)的关系
    @ToMany:定义与多个实体对象的关系
    

    五、使用greenDAO 进行数据操作(详情可查阅博友的文章

    • 使用单例模式构建一个工具类来获取daoSession等对象
    public class GreenDaoHelper {
    
        private static DaoMaster.DevOpenHelper devOpenHelper;
        private static SQLiteDatabase database;
        private static DaoMaster daoMaster;
        private static DaoSession daoSession;
    
        /**
         * 初始化greenDao
         * 建议放在Application 中进行
         */
    
        public static void initDatabase(){
            // 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 SQLiteOpenHelper 对象。
            // 可能你已经注意到了,你并不需要去编写「CREATE TABLE」这样的 SQL 语句,因为 greenDAO 已经帮你做了。
            // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。
            // 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。
            devOpenHelper = new DaoMaster.DevOpenHelper(AppContext.getInstance(),"cache-db",null);//数据库名
            database = devOpenHelper.getWritableDatabase();
            // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
            daoMaster = new DaoMaster(database);
            daoSession = daoMaster.newSession();
        }
    
        public static DaoSession getDaoSession() {
            return daoSession;
        }
        public static SQLiteDatabase getDb() {
            return database;
        }
    }
    

    数据库的增删改查我们都将通过Dao来操作

    • 增加数据(直接inser一个对象即可,十分简便)
     private UserDao mUserDao = GreenDaoHelper.getDaoSession().getUserDao();
    
        public void insertData(){
            //数据库的增删改查我们都将通过UserDao来进行,插入操作如下:
            mUserDao.insert(new User(null,"david",23,"male"));//id传null 即自增。==> 这里是Long类型而不是long
        }
    

    小手一抖,一口气插了6条数据:

    小手一抖,一口气插了6条数据
    • 删除数据(删除数据和修改数据的思路一样,都是要先查找到数据),操作很简单,效果就不一一截图了
    //查询id等于3的所有行并删除
    User user = mUserDao.queryBuilder().where(UserDao.Properties.Id.eq(3)).build().unique();
    if (user == null)   ToastUtils.show(getView(), "用户不存在!");
    else   mUserDao.deleteByKey(user.getId());
    
    //查询id小于5的集合并删除
    List<User> userList = (List<User>) mUserDao.queryBuilder().where(UserDao.Properties.Id.le(5)).build().list();
    for (User user : userList) {
        mUserDao.delete(user);
    }
    
    //删除所有数据
    mUserDao.deleteAll();
    
    
    • 修改数据
    //修改id为2的行 
    User user = new User((long) 2, "Nancy", 23, "female");
    mUserDao.update(user);
    
    //查询id>= 3 且like ("%david%")
    User user = mUserDao.queryBuilder()
                    .where(UserDao.Properties.Id.ge(3), UserDao.Properties.UserName.like("%david%")).build().unique();
    if (user == null) {
        ToastUtils.show(getView(), "用户不存在!");
    } else {
        user.setUserName("王五");
        mUserDao.update(user);
    }
    
    
    • 查询数据
    //查出所有数据
    List<User> users = mUserDao.loadAll();    
    
    //查询id为1~4之间的数,查出前2个
    List<User> users = mUserDao.queryBuilder()
                    .where(UserDao.Properties.Id.between(1, 4)).limit(2).build().list();
    

    六、数据库升级

    数据库升级的意义:

    如果我们再项目中使用了数据库。而数据库的结构在第一版的时候定下来,之后发布功能更新,或增加业务逻辑,原来的数据库结构可能就不适用了。而如果数据库的结构与之前版本的结构不同,新版本的应用读取旧数据库肯定会出问题。解决办法只有两种:
    1.让用户卸载老版本再安装新的程序;
    2.软件自行更新数据库结构。
    第一种办法很明显不具备可操作性,而且用户一旦卸载软件,数据就丢失了,这是不能容忍的事情。因此,作为开发者必须妥善处理数据库的升级问题。

    • 修改gradle文件

    首先在module的gradle文件中修改版本号:

    //改为最新的版本号  
    schemaVersion 2  
    

    如果只是做了上面的步骤则会默认清除所有数据,一看源码便知,当检测到version变化的时候便执行dropAllTables()操作,再重新建库

        /** WARNING: Drops all table on Upgrade! Use only during development. */
        public static class DevOpenHelper extends OpenHelper {
            public DevOpenHelper(Context context, String name) {
                super(context, name);
            }
    
            public DevOpenHelper(Context context, String name, CursorFactory factory) {
                super(context, name, factory);
            }
    
            @Override
            public void onUpgrade(Database db, int oldVersion, int newVersion) {
                Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
                dropAllTables(db, true);
                onCreate(db);
            }
        }
    

    数据迁移的核心思想:
    1 把旧表改为临时表
    2 建立新表
    3 临时表数据写入新表,删除临时表

    站在巨人的肩膀上,这里直接使用了开源的库,配合greenDAO来做数据迁移,亲测稳定:
    GreenDaoUpgradeHelper

    schemaVersion 版本加1,User类新增属性:major

    不做迁移处理前,重新安装后数据库已经被重置,数据为空。迁移配置后,旧表数据已经被存到新表中,major字段为null;


    数据迁移成功

    使用方式该git上面介绍的很详细了,不再赘述。
    感谢前辈们的无私分享。

    相关文章

      网友评论

      • 过期的薯条:用这个库之后 dao 老提示没实现getKey方法
      • zhangkun9527:在MigrationHelper类中的isTableExists方法中,有如下代码:
        String dbName = isTemp ? SQLITE_TEMP_MASTER : SQLITE_MASTER;
        String sql = "SELECT COUNT(*) FROM " + dbName + " WHERE type = ? AND name = ?";
        感觉是这个地方出问题了,为什么备份的时候是在原数据库下创建临时表,备份完数据之后,是从一个新的数据库中判断表是否存在,这个判断有问题吧,为什么不是从原数据库中判断表是否存在?数据库升级过程中,没有创建新的数据库,只是在原数据库中创建了新表。奇怪,没看明白。
      • 爱吃板栗的小女孩:你好,我也用了那个库升级,但是我在改完版本号以后,运行数据就丢了,也写了onUpgrade()里方法,应该操作不对,你知道哪里出错了吗
        zhangkun9527:https://stackoverflow.com/questions/13373170/greendao-schema-update-and-data-migration/30334668#30334668
      • youyuge:“而jcenter仓库就是maven仓库的一个分支”这句话有误,jcenter确实是maven仓库,但是两个标准的Android library文件服务器:jcenter 和 Maven Central是不同的。所以mavenCentral()这句话必须要加!
      • studentliubo:博主知道分页查询是怎么搞得不咯?
      • bingoCode:如果是用了GreenDaoUpgradeHelper ,还需要本地更改schemaVersion 版本号吗
        bingoCode:@david_zhw 嗯嗯 谢谢
        david_zhw:@bingoCode 要的,版本更新才会生效
      • 无心下棋:亲测,数据被清空了 。。。。
        david_zhw:@无心下棋 自己认真测试了再下结论呀,看我最后一张图,第一个查询语句查出的结果为空的,第二个查询语句是在数据成功迁移之后的,可以看出我新数据新增了专业这个字段
        无心下棋: @david_zhw 😂那个开源项目的作者都说会被清空。
        david_zhw:请确认下操作是否正确哦,我测试是成功的

      本文标题:greenDAO3 入门(配置,基本操作,数据库升级)

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