Greendao快速使用

目录索引

1.依赖添加

2.数据库创建与升级

3.实体类编写

4.使用数据库

5.QueryBuilder 自定义实体查询Api


1.依赖添加

在根目录下的build.gradle添加配置:

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        //greendao配置
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

 接着在app下的build.gradle文件添加配置:

apply plugin: 'com.android.application'
//1.添加插件
apply plugin: 'org.greenrobot.greendao'
android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.test.demo"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    greendao {
         //2.指定数据库版本号,迁移等操作会用到
         schemaVersion 3
    }
}

dependencies {
   //添加依赖
   implementation 'org.greenrobot:greendao:3.2.2'
}

2.数据库创建与升级

依赖已经添加到我们的项目中了,接下来是使用。首先要初始化几个参数:

private MyDateBaseHelper mHelper= new MyDateBaseHelper(new GreenDaoContext(instance), "数据库名称");
private SQLiteDatabase mDatabase = mHelper.getWritableDatabase();
private DaoSession mDaoSession = mDaoMaster.newSession();
private DaoMaster mDaoMaster= new DaoMaster(mDatabase);

 MyDateBaseHelper呢是一个继承至 DaoMaster.DevOpenHelper的一个类,当然也可以直接使用DaoMaster.DevOpenHelper对象代替MyDateBaseHelper类:

DaoMaster.DevOpenHelper mHelper = new DaoMaster.DevOpenHelper(new GreenDaoContext(instance), "数据库名称");

说明一下作为Context 类型的实例的 GreenDaoContext(instance)类。这个类继承了ContextWrapper,主要自定义数据库创建路径。默认情况下我们的数据库是在data/data/....路径下,而使用自定义路径的数据库会方便管理。这个方法也是来源于其他前辈,博主的。(感谢前辈,大佬铺路QAQ)

public class GreenDaoContext extends ContextWrapper {

    private static String TAG = "GreenDaoContext";
    /**
     * SD卡下文件目录名称
     * 一般用来针对一个用户一个数据库,以免数据混乱问题
     */
    private String currentUserId = "数据库所在文件夹名称";
    private Context mContext;
    public GreenDaoContext(Context context) {
        super(context);
        this.mContext = context;
    }
    /**
     * 获得数据库路径,如果不存在,则创建对象
     * @param dbName
     */
    @Override
    public File getDatabasePath(String dbName) {
        //选择sdcard作为数据库存放路径
        String dbDir = Environment.getExternalStorageDirectory().getPath();
        if (TextUtils.isEmpty(dbDir)) {
            return null;
        }
        File baseFile = new File(dbDir);      
        if (!baseFile.exists()) {
            baseFile.mkdirs();
        }
        StringBuffer buffer = new StringBuffer();
        buffer.append(baseFile.getPath());
        buffer.append(File.separator);
        buffer.append(currentUserId);
        dbDir = buffer.toString();// 数据库所在目录
        buffer.append(File.separator);
        buffer.append(dbName);
        String dbPath = buffer.toString();// 数据库路径
        Log.d(TAG, dbPath);
       
        File dirFile = new File(dbDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }       
        boolean isFileCreateSuccess = false;       
        File dbFile = new File(dbPath);               
        if (!dbFile.exists()) {
            try {
                isFileCreateSuccess = dbFile.createNewFile();// 创建文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else
            isFileCreateSuccess = true;
        // 返回数据库文件对象
        if (isFileCreateSuccess)
            return dbFile;
        else
            return super.getDatabasePath(dbName);
    }

    /**
     * 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。     *
     * @param name
     * @param mode
     * @param factory
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
        return result;
    }
    /**
     * Android 4.0会调用此方法获取数据库。     *
     * @param name
     * @param mode
     * @param factory
     * @param errorHandler
     * @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int,
     * android.database.sqlite.SQLiteDatabase.CursorFactory,
     * android.database.DatabaseErrorHandler)
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
        return result;
    }

}

 MyDateBaseHelper:

public class MyDateBaseHelper extends DaoMaster.DevOpenHelper {
    public MyDateBaseHelper(Context context, String name) {
        super(context, name, null);
    }
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        //数据库升级
        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);
            }
        }, xxxxDao.class,yyyyDao.class,.....);
    }
}

 MigrationHelper是数据库升级处理方法,因为这个工具类篇幅太长,另开一篇记录MigrationHelper数据升级库迁移类

3.实体类编写

实体类跟自己写的普通数据类是一样的,只是多了一些数据的注解,如下例子:

@Entity(nameInDb = "goods")
public class Goods{
    @Id(autoincrement = true)
    private Long id;
    private Long goodsId;
}

 其中@Entity(nameInDb = "goods")就是标识这个数据类在数据库里的表名称为 goods。@ID则是作为表中的主键,后面的autoincrement = true则表示为自动增长。其他的注解:

  • @Convert :指定该字段为PropertyConverter支持的自定义类型。要在实体中使用自定义类型,要实现PropertyConverter接口,将db值转换为实体值并返回。
  • @Entity(nameInDb = "goods") : 声明为这是一个表,只有被这个注解的实体类才能进行dao操作。可设置8个参数;参数 nameInDb 表示表名,默认为类名;还有其他参数:createInDb-是否创建表在数据库,默认为true;generateConstructors-是否自动生成构造方法,默认为true;indexes-实体类的索引;generateGettersSetters-是否自动创建getset方法,默认true等等,只列举几个比较容易用到的。
  • @Generated :表示为自动生成的代码,不能被修改。
  •  @Id(autoincrement = true) :声明为数据库主键。只有一个参数:autoincrement- 为是否自动增长,默认为false
  • @Index :指定这个属性可以被索引,有3个参数:value-编入索引的属性列表,只有当@Entity设置了indexes参数时才应该设置这个值;name-索引的别名;unique-是否以此属性创建唯一约束,默认false。
  • @JoinEntity :用于连接表定义表关系(多数用于多对多关系,需要定义中间表的时候)。有3个参数:entity-两个关系表的中间表(类),sourceProperty-持有源(当前实体)的属性(字段),多定义为当前实体主键;targetProperty-对应目标的属性(字段)。
  • @JoinProperty :为表关系定义name和referencedName关联属性。
  • @Keep :使用此注解的目标在greenDAO生成的下一次运行期间保存,不会发生修改。在实体类本身上使用此注释将禁用任何类修改,用户负责编写和支持greenDAO所需的任何代码。通常情况下不要在类成员上使用此注释,因为发生模型变更时,greenDAO将无法对目标代码进行相应的变更。
  • @NotNull  :该字段不能为null。
  • @OrderBy :排序。注意指定为ToMany下关系的排列顺序,使用如@OrderBy("name DESC"),字段名称,排序顺序
  • @Property(nameInDb = "") :声明为数据库中字段名称。默认为类属性名称。
  • @ToMany :表关系,一对多或多对多。
  • @ToOne :表关系,一对一。
  • @Transient : 表示该属性不会在数据库中生成对应的字段
  • @Unique :是否以此属性创建唯一约束,默认false

实体类也编写好了,需要使用AS 工具make project(绿色的锤子)就会自动生成相关的dao,配置等代码。

4.使用数据库:

为了方便使用,会有一个专门的类去定义所有的操作数据方法,也就是crud。

插入数据

 public boolean insert(Goods goods) {
        Long row = goodsDao.insert(goods);
        return row > 0;
    }

以上代码,传入Goods对象(Goods就是前面定义的实体类了),通过对应的dao来操作。***Dao是所有greendao数据库操作的直接发起对象。获取这个***Dao

private GoodsDao goodsDao = mDaoSession.getGoodsDao();

 mDaoSession就是第二步骤里实例化的DaoSession 对象。

删除数据

 public boolean delete(Goods goods) {
        goodsDao.delete(goods);      
    }

 //删除所有数据
 public boolean deleteAll() {
        goodsDao.deleteAll();      
    }

更新数据

 public boolean update(Goods goods) {
        goodsDao.update(goods);      
    }

查询数据

//查询所有 
public List<Goods> queryAll() {
        goodsDao.detachAll();     
        return goodsDao.loadAll();
    }

//查询所有商品的价格属性等于price的商品,以list形式返回
 public List<Goods> queryByGoodsId(String price) {
        goodsDao.detachAll();
        return goodsDao.queryBuilder().where(goodsDao.Properties.Price.eq(price))
                .list();
    }

//查询商品goodsid等于id的商品。因为goodsid为主键,只会存在一条,所以可以直接返回goods对象
 public Goods queryByGoodsId(Long id) {
        goodsDao.detachAll();
        return goodsDao.queryBuilder().where(goodsDao.Properties.GoodsId.eq(id))
                .unique();
    }

以上查询代码说明:

  •  goodsDao.detachAll():这是作为清除greendao的查询缓存。因为使用特殊的查询方式会产生缓存,可能会影响查询结果。看情况使用。
  • queryBuilder().where(.....):Greendao快捷查询,可以不使用原始的sql语句构建查询语句。queryBuilder().Where()的作用等同于创建原始的sql语句,并且会在编译时加入错误检查。
  • goodsDao.Properties.Price.eq(price):很好理解,就是一个条件语句,*****等于*****。

使用queryBuilder来查询的方式称作为自定义实体查询。

5.QueryBuilder 自定义实体查询Api:

or :或者。连接多个条件查询, WhereCondition类型,不能独立使用,配合where或者whereOr使用。

and:并且。连接多个条件查询, WhereCondition类型,不能独立使用,配合where或者whereOr使用。

where :添加查询条件。QueryBuilder类型,使用逻辑和向where子句添加给定的条件。

unique :执行查询并返回唯一的结果或null,返回实体对象或null。如果结果不是唯一的,则抛出dao异常。

build :构建一个可重用的查询对象,查询对象可以比创建QueryBuilder更有效地执行。说简单了就是提供缓存,如果查询参数有变化,需要对每一个改变的parameter调用setParameter方法。可以通过下标index访问parameter。unique()li里面就有使用到。

例子:

//用Query 查询出生在1970年并且first name为“Joe”的人:
Query query = userDao.queryBuilder().where(
Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
.build();
List joesOf1970 = query.list();
//使用上面的查询对象,通过修改参数,不需要重新创建query,查询1977年之后出生的 Marias
query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List mariasOf1977 = query.list();

buildCount:构建一个可重用的查询对象来计数行,类似build,只是buildCount更多用来返回一个符合条件的数量。

buildCursor:为低层android.database构建一个可重用的查询对象,为指针访问。最终数据会以游标形式返回。

buildDelete:创建一个符合条件的删除DeleteQuery类型对象。执行时,删除所有匹配的实体,但是不会将它们从缓存中分离出来。这方法可能导致会话缓存中的过期实体对象。加载时,可以返回陈旧的实体

count :作用等同于buildCount。

distinct :QueryBuilder类型。避免返回重复的实体,例如如在进行连表连接时

join:连表查询。

limit :限制查询返回的结果数量。

list :将所有的查询返回以一个list形式返回。所有的实体被加载到内存中。该结果通常是一个没有magic involved的ArrayList。使用起来最简单。

listLazy:同list。实体按照需求加载进入内存。一旦列表中的一个元素被第一次访问,它将被加载同时缓存以便以后使用。必须close。

listIterator:遍历通过需要的时候加载(lazily)获得的结果,数据没有缓存,必须close。

listLazyUncached :一个“虚拟”的实体列表:任何对列表元素的访问都会导致从数据库中加载,必须close。

offset:偏移量,跳过前几个数据。配合limit使用。

orderAsc:根据字段属性升序排序返回。需要传入排序字段参数。

orderDesc :根据字段属性降序排序返回。需要传入排序字段参数。

orderRaw:只将给定的原始SQL字符串添加到order by后面部分,为string类型参数。最终结果等同于orderAsc或者orderDesc。

orderCustom:根据给定的字段属性依照添加到order by后面的部分SQL字符串来排序。传入字段属性,排序条件两个参数。

preferLocalizedStringOrder:使用Android的嵌入式SQLite,也就是混合语句,这将支持对字符串进行本地化排序。配合orderAsc跟orderDesc一起使用的吧,

rx:build()的另一种缩写形式。可以使用RX的Observables来返回结果,使用的是io调度。(参考Rxjava下的调度器)。

rxPlain:同rx。不使用任何调度器。

uniqueOrThrow:同unique(),返回唯一实体对象,不能为null。如果返回不是唯一的或者为null了,则抛出dao异常。

stringOrderCollation:自定义使用排序字符串的使用顺序,类似 preferLocalizedStringOrder(),需要传入一个String参数。

whereOr:使用or逻辑添加查询条件,类似where。内部使用了or()逻辑。

 条件逻辑api

  • eq:等于逻辑,equal缩写。等价SQL语句的  =?。
  • notEq:不等于。等价SQL语句的 <>。
  • like:模糊查询。等价SQL语句 like ?。
  • between:两者之间。等价SQL语句 between... and ... 。
  • in:范围查询。等价SQL语句 in (..,...)。可传入多个参数。
  • notIn:不在范围内。等价SQL语句 not in (...,...)。
  • gt:大于条件,greater than的缩写。等价SQL语句 >?。
  • lt:小于条件,less than的缩写。等价SQL语句 <?。
  • ge:大于等于条件,greater equal的缩写。等价SQL语句 >=?。
  • le:小于等于条件,less equal的缩写。等价SQL语句 <=?。
  • isNull:空条件。等价SQL语句 is null 。
  • isNotNull:不为空条件。等价SQL语句 is not null。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值