Android 数据库--greenDAO 3.0 的基本使用方法

安卓开发主要使用的存储方式有三种:

文件存储
数据库存储
网络存储

一般轻量级存储,我们使用文件存储就够用了,但是一旦涉及大量存储数据时候,文件存储就显得很笨重了,这个时候就需要我们使用数据库存储了,android系统是自带 SQLite轻量级嵌入式数据库引擎,并提供了相应的调用api,但是书写复杂,大多数开发者都会选择封装后再使用,或者挑选一个开源库来使用。目前主流的的数据库有:

LitePal 郭霖大神出品的一款开源的orm数据库

afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用。FinalDB模块,android中的orm框架,一行代码就可以进行增删改查。支持一对多,多对一等查询。

ORMLite(Object Relational Mapping Lite)提供了一些轻量级持久化Java对象到SQL数据库,同时也避免了复杂性和更多的标准的ORM包的开销功能。它支持的SQL数据库使用JDBC的数量,还支持原生的Android操作系统数据库API调用sqlite

SugarORM 是对象关系映射模式。不用写复杂的sql语句,而用简单的API即可完成创建和操纵数据;可以在原有的Bean上仅仅添加小的修改而复用Bean;简化而明了的数据库设计和创建过程,同时提供表的一对多的支持。

Realm 是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。

LiteOrmDBFlow

本文主要讲解greenDAO 3.0 GreenDao是为Android设计的对象关系映射(ORM)工具。它提供了对象到关系型数据库SQLite的相应接口。为了在Android工程中使用greenDao,需要创建另一个“生成器”工程,它的任务是在你的工程域里生成具体的代码。因此相比与其它ORM框架具有出众性能。

基本用法

第一步,在根目录(最外层)下的 build.gradle内添加 greenDao 插件

// In your root build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'  //这个是当前用的 gradle 版本
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}

第二步,在工程目录下的 build.gradle 内添加相关依赖

// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // add library  compile 在新版gradle里已经不建议使用了
}

第三步 指定greenDao 自动生成代码的目录,在工程目录下的 build.gradle 添加如下

greendao {
    schemaVersion 1 //指定数据库schema版本号,迁移等操作会用到
    daoPackage 'xxx.xx.xxx.greendao'//通过gradle插件生成的数据库相关文件  xxx.xxx.xx 一般填写包名
    targetGenDir 'src/main/java'  //自定义生成数据库文件的目录
}

第三步 编写自己所需要的实体类 对实体类加一些注解 此处以我写的代码分析一哈

@Entity //这个注解必须要 告诉greenDao这是一个实体类
public class TokenEntity implements Serializable {
    static final long serialVersionUID = -15515456L;
    @Id  //标识为id  可选 还有大量注解 可查询官方文档
    private String id;
    private String address;
    private String name;
    private String tag;
    private String tokenAddress;
    private double balance;

一些常用注解
@Entity 用于标识这是一个需要Greendao帮我们生成代码的bean

@Id 标明主键,括号里可以指定是否自增

@Property 用于设置属性在数据库中的列名(默认不写就是保持一致)

@NotNull 非空

@Transient 标识这个字段是自定义的不会创建到数据库表里

@Unique 添加唯一约束

第四步,自动生成代码,点击make project greenDAO插件 会帮我们生成一些文件。


image.png

首先实体类的变化,构造方法和set,get方法都自动生成

@Entity
public class TokenEntity implements Serializable {
    static final long serialVersionUID = -15515456L;
    @Id
    private String id;
    private String address;
    private String name;
    private String tag;
    private String tokenAddress;
    private double balance;
    private long decimals; //精度
    @Generated(hash = 194050609)
    public TokenEntity(String id, String address, String name, String tag,
            String tokenAddress, double balance, long decimals) {
        this.id = id;
        this.address = address;
        this.name = name;
        this.tag = tag;
        this.tokenAddress = tokenAddress;
        this.balance = balance;
        this.decimals = decimals;
    }
....

项目里src下也会新增相关类,DaoMaster,DaoSession和实体类的Dao


image.png

不封装基本使用,非常不建议

//DB_NAME 自己定义的数据库名字
 DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(RuntimeContext.getApplication(),DB_NAME,null); 
        mDaoMaster = new DaoMaster(devOpenHelper.getWritableDb());
        mDaoSession = mDaoMaster.newSession();
        mDaoSession.getTokenEntityDao().insert(new TokenEntity()); //获取实体类的entityDao api 提供增删改查

简单封装
DBManager.class 单例模式 获取数据库的 master 和session

/**
 * 数据库管理类
 */
public class DBManager {
    final static String DB_NAME = "xxx_db";
    private static DBManager mInstance;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private DBManager(){
        DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(RuntimeContext.getApplication(),DB_NAME,null);
        mDaoMaster = new DaoMaster(devOpenHelper.getWritableDb());
        mDaoSession = mDaoMaster.newSession();
    }

    public DaoMaster getDaoMaster() {
        return mDaoMaster;
    }

    public DaoSession getDaoSession() {
        return mDaoSession;
    }
    public static DBManager getInstance(){
        if(mInstance==null){
            synchronized (DBManager.class){
                if(mInstance==null){
                    mInstance = new DBManager();
                }
            }
        }
        return mInstance;
    }
}

针对每个实体类编写工具类,后期替换别的数据库,或者改动会方便很多,此处以我写的token实体编写增删改查工具类,本来想通过反射写一个通用的增删改成类,结果发现查的时候每个表的属性都不一样就放弃。

/**
 * 负责token 表的增删改查
 */
public class TokenDbUtil {
    public static boolean insert(TokenEntity entity){
        try {
            DBManager.getInstance().getDaoSession().getTokenEntityDao().insert(entity);
        }catch (Exception e){
            return false;
        }
        return true;
    }
    public static boolean insertOrReplace(TokenEntity entity){
        try {
            DBManager.getInstance().getDaoSession().getTokenEntityDao().insertOrReplace(entity);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    /**
     * 批量插入
     * @param list
     * @return
     */
    public static boolean insertBatch(List<TokenEntity> list){
        try {
            DBManager.getInstance().getDaoSession().getTokenEntityDao().insertInTx(list);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    public static boolean update(TokenEntity entity){
        try {
            DBManager.getInstance().getDaoSession().getTokenEntityDao().update(entity);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    /**
     * 通过地址查询 该address下拥有的token
     * @param address
     * @return
     */
    public static List<TokenEntity> queryByAddress(String address){
        List<TokenEntity> list = null;
        list =DBManager.getInstance().getDaoSession().getTokenEntityDao()
                .queryBuilder()
                .where(TokenEntityDao.Properties.Address.eq(address)).build().list();
        return list;
    }

    public static boolean delete(TokenEntity entity){
        try {
            DBManager.getInstance().getDaoSession().getTokenEntityDao().delete(entity);
        }catch (Exception e){
            return false;
        }
        return true;
    }
}

greenDAO 基本使用方法就写到这里了。

greenDAO 开发中遇到的一些小坑

1.开发中突然想加一些实体类属性,发现在跑App时报各种错,删掉App重新装,因为新增属性,会改变表结构,而又没有更新build.gradle 里版本号, 数据库就会出错。
2.实体类序列化,一开始没想到该实体类需要序列化,再加上 implements Serializable 代码时候出各种错,删掉代码里的@Generated(hash = xxxxx) 重新 make project

  1. 各种打印java.lang.ClassNotFoundException: Didn’t find class “net.sqlcipher.database.SQLiteOpenHelper
    的log , 虽然不影响使用,但是还是很烦,因为greenDAO 用到加密相关的东西,而这个库没有被加入,在build.gradle 里加入
implementation 'net.zetetic:android-database-sqlcipher:3.4.0@aar'

就不报这个异常了。这里又有一个坑,官方文档给的 https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
版本可能不存在,当初按官网文档走,怎么都下载不下来。由于多加了一个库,App体积也变大了不少,如果没有用到加密库,那就不用加这个库了。看到这里了,点个赞呗。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容