GreenDAO是一个开源的安卓ORM框架,。它减轻开发人员处理低级数据库需求,同时节省开发时间。 SQLite是一个内嵌的关系数据库,编写SQL和解析查询结果是相当乏味和耗时的任务。通过将Java对象映射到数据库表(称为ORM,“对象/关系映射”),GreenDAO可以将它们从这些映射中释放出来,这样,您可以使用简单的面向对象的API来存储,更新,删除和查询数据库。简单的,GreenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。
与2.0的区别:GreenDao 3.0采用注解的方式来定义实体类,通过gradle插件生成相应的代码。您可以使用greenDAO Gradle插件,无需任何其他配置,但至少要设置schema的版本等;
使用前你需要添加greenDAO Gradle插件并添加greenDAO库:
做法:首先在你的工程的gradle文件中添加相应的依赖
buildscript { repositories { jcenter() mavenCentral() // add repository } dependencies { classpath 'com.android.tools.build:gradle:3.1.1' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin } }
然后在你具体使用的app modules的gradle文件里添加相关的插件依赖和函数库
apply plugin: 'com.android.application' apply plugin: 'org.greenrobot.greendao' // apply plugin dependencies { implementation 'org.greenrobot:greendao:3.2.2' // add library
这样算是配置完成啦
首先我们看看官方的文档:
要在项目中使用greenDAO,您需要创建一个实体模型来表示应用程序中的持久性数据。然后,基于该模型, greenDAO为DAO类生成Java代码。
意思是你需要建立实体类去代表你要在数据库中要生成的表的数据。GreenDao可以通过你建立的实体类去生成相应的表,并根据你的实体类对象为你自动生成操作数据库的相关java类,而这些的实现,GreenDao3.0后是通过注解的形式实现的。
注意: 我们无需任何其他配置即可开始使用greenDAO Gradle插件。不过,应该设置架构版本:
在工程的gradle文件中添加相应设置架构版本的代码:
android { ... } greendao { schemaVersion 2 // daoPackage "com.example.model" // set package of generated classes }
此外,greendao配置元素支持许多配置选项:
好啦我们开始创建我们的实体类啦:
@Entity
public class User {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "USERNAME")
private String name;
@NotNull
private int repos;
@Transient
private int tempUsageCount;
}
这是我们创建的实体类,你会发现代码里面包含着注释,那这些注释的作用是什么呢?
@Entity注解打开Java类 用户到数据库支持的实体。这还将指示greenDAO生成必要的代码(例如DAO)。
注意:仅支持Java类。如果您喜欢Kotlin等其他语言,则您的实体类必须仍然是Java。
Entity就是实体的意思这个注释可以让GreenDao识别, 将我们的java普通类变为一个能够被greenDAO识别的数据库类型的实体类;
@Entity 不需要任何其他参数也可以,但是你也可以使用**@Entity**配置一些细节 用法如下:
@Entity(
// 如果您有多个模式,可以告诉greenDAO
// 实体属于哪个模式(选择任何字符串作为名称)。
schema = "myschema",
// 标记使一个实体“活动”:活动实体有更新
// 删除和刷新方法
active = true,
//指定数据库中表的名称。
// 默认情况下,名称基于实体类名。
nameInDb = "AWESOME_USERS",
//定义跨越多个列的索引。
indexes = {
@Index(value = "name DESC", unique = true)
},
//标记DAO是否应该创建数据库表(默认为true)。
//如果你有多个实体映射到一个表,
//或者在greenDAO之外创建表。
createInDb = false,
//是否应该生成一个all properties构造函数。
//总是需要一个无参数的构造函数。
generateConstructors = true,
//如果缺少属性的getter和setter是否应该生成。
generateGettersSetters = true
)
public class User {
...
}
@Id注释选择 long / Long属性作为实体ID。用数据库术语来说,它是主键。参数autoincrement 是使ID值不断增加(不重用旧值)的标志。
@Property允许您定义一个非默认列名,该属性映射到该列名。如果不存在,greenDAO将以类似于SQL的方式使用字段名称(大写字母,下划线而不是驼峰字母,例如 customName将变为 CUSTOM_NAME)。
@NotNull使该属性在数据库端成为“ NOT NULL”列。通常,使用@NotNull标记原始类型(long,int,short,byte)是有意义的,同时使用包装类(Long,Integer,Short,Byte)具有可空值。
@Transient标记要从持久性中排除的属性。将它们用于临时状态等。或者,您也可以使用Java中的transient关键字。
主键限制
当前,实体必须具有 long或 Long属性作为其主键。这是Android和SQLite的推荐做法。
意思就是表的主键必须是long或 Long类型的但是我们可以通过为其他字段添加一个唯一不重复的索引来使这个字段拥有和主键一样的唯一标示性,那么这个字段虽然不是主键,却可以像主键一样的使用。
要解决此问题,请将您的key属性定义为其他属性,但为其创建一个唯一索引:
@Entity public class User { @Id private Long id; @Index (unique = true) private String name; }
在属性上使用**@Index**为相应的数据库列创建数据库索引。使用以下参数进行自定义:
name:如果您不喜欢greenDAO为索引生成的默认名称,则可以在此处指定您的名称。
unique:向索引添加UNIQUE约束,强制所有值都是唯一的。
greenDAO尝试使用合理的默认值,因此开发人员不必每次都进行配置。
例如,数据库端的表名和列名是从实体名和属性名派生的。代替Java中使用的驼峰式样式,默认数据库名称使用大写字母,使用下划线分隔单词。
例如,名为creationDate的属性 将成为数据库列 CREATION_DATE。
最后我们通过注释声明啦一个实体类,我们点击Android studio 的Build------>make project
然后我们就会发现在我们的module中自动生成啦一些东西,并且我们的实体类也多啦get set的方法。
到这里我们就用GreenDao构造啦实体。下面介绍一下生成的这几个类:
这里要解释一下生成的三个核心类的作用:
DaoMaster:DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。 它具有静态方法来创建表或将它们删除。 其内部类OpenHelper和DevOpenHelper是在SQLite数据库中创建模式的SQLiteOpenHelper实现。一个DaoMaster就代表着一个数据库的连接。
DaoSession:管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取。 DaoSession还为实体提供了一些通用的持久性方法,如插入,加载,更新,刷新和删除。 DaoSession可以让我们使用一些Entity的基本操作和获取Dao操作类,DaoSession可以创建多个,每一个都是属于同一个数据库连接的。
XxxDAO:数据访问对象(DAO)持续存在并查询实体。 对于每个实体,GreenDAO生成一个DAO。 它比DaoSession有更多的持久化方法,例如:count,loadAll和insertInTx。
我们知道数据库表可以使用1:1、1:N或N:M关系相互关联。通过主外键的形式把多张表进行联系。
在GreenDao中仍然是通过注解的形式实现的。
一对一关系建模:
所述**@ToOne**注释定义一个相对于另一实体(一个实体对象)。将其应用于持有另一个实体对象的属性。
在内部,greenDAO需要一个额外的属性,该属性指向目标实体的ID,该属性由joinProperty参数指定。如果不存在此参数,则会自动创建一个附加列来保存键。
实例代码:我们创建两个实体类,一个Son类,一个Father类。假设一个父亲对应一个儿子,一个儿子对应一个父亲。
/**
* Created by zhongzai on 2019/10/25
*/
@Entity
public class Father {
@Id
private Long _id;
@Property(nameInDb = "NAME")
private String name;
@Property(nameInDb = "age")
private int age;
}
/**
* Created by zhongzai on 2019/10/25
*/
@Entity
public class Son {
@Id
private Long _id;
private long fatherId;
@ToOne(joinProperty = "fatherId")
private Father father;
}
对多关系建模
@ToMany定义与一组其他实体(多个实体对象)的关系。将此属性应用于代表目标实体列表的属性 。所引用的实体必须具有一个或多个指向拥有@ToMany的实体的属性。
有三种可能性可以指定关系映射,请仅使用其中一种:
@Entity public class Customer { @Id private Long id; @ToMany(referencedJoinProperty = "customerId") @OrderBy("date ASC") private List<Order> orders; } @Entity public class Order { @Id private Long id; private Date date; private long customerId; }
@Entity public class Customer { @Id private Long id; @Unique private String tag; @ToMany(joinProperties = { @JoinProperty(name = "tag", referencedName = "customerTag") }) @OrderBy("date ASC") private List<Site> orders; } @Entity public class Order { @Id private Long id; private Date date; @NotNull private String customerTag; }
@Entity public class Product { @Id private Long id; @ToMany @JoinEntity( entity = JoinProductsWithOrders.class, sourceProperty = "productId", targetProperty = "orderId" ) private List<Order> ordersWithThisProduct; } @Entity public class JoinProductsWithOrders { @Id private Long id; private Long productId; private Long orderId; } @Entity public class Order { @Id private Long id; }
还有其他模式:参考官方文档 http://greenrobot.org/greendao/documentation/relations/
创建一个类用来管理数据库的创建,数据库表的创建、增删改查的操作以及数据库的升级
package com.example.sqlite_greendao.zhongzai;
import android.content.Context;
import com.greendao.gen.DaoMaster;
import com.greendao.gen.DaoSession;
/**
* 创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级
* Created by zhongzai on 2019/10/25
*/
public class MyDaoManager {
private static final String DB_NAME = "mydbtest";
private Context context;
private static MyDaoManager manager = new MyDaoManager();
private static DaoMaster master;
private static DaoMaster.DevOpenHelper helper;
private static DaoSession daoSession;
/**
* 使用单例模式获得操作数据库对象
*/
public static MyDaoManager getInstance() {
return manager;
}
public void init(Context context) {
this.context = context;
}
/**
* 判断是否有存在数据库,如果没有则创建
*/
public DaoMaster getDaoMaster() {
if (master == null) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
master = new DaoMaster(helper.getWritableDatabase());
}
return master;
}
/**
* 对数据库的添加、删除、修改、查询操作,仅仅是一个接口不是对象
*/
public DaoSession getDaoSession() {
if (daoSession == null) {
if (master == null) {
master = getDaoMaster();
}
daoSession = master.newSession();
}
return daoSession;
}
/**
* 关闭所有的操作,数据库开启后,使用完毕要关闭
*/
public void closeConnection() {
if (helper != null) {
helper.close();
helper = null;
}
if (daoSession != null) {
daoSession.clear();
daoSession = null;
}
}
}
为father表创建一个工具类用来实现对father表的增删改查
package com.example.sqlite_greendao.zhongzai;
import android.content.Context;
import com.example.sqlite_greendao.Father;
import com.greendao.gen.FatherDao;
import org.greenrobot.greendao.query.QueryBuilder;
import java.util.List;
/**
* Created by zhongzai on 2019/10/25
*/
public class FatherDaoUtils {
private MyDaoManager mManager;
public FatherDaoUtils(Context context) {
mManager = mManager.getInstance();
mManager.init(context);
}
/**
* 完成father记录的插入,如果表未创建,先创建father表
*/
public boolean insert(Father father) {
boolean flag = false;
if (mManager.getDaoSession().getFatherDao().insert(father) == -1) {
flag = false;
} else {
flag = true;
}
return flag;
}
/**
* 修改一条数据
*/
public boolean updateFather(Father father) {
boolean flag = false;
try {
mManager.getDaoSession().update(father);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除单条记录
*/
public boolean deleteFather(Father father) {
boolean flag = false;
try {
//按照id删除
mManager.getDaoSession().delete(father);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除所有记录
*/
public boolean deleteAll() {
boolean flag = false;
try {
//按照id删除
mManager.getDaoSession().deleteAll(Father.class);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 查询所有记录
*/
public List<Father> queryAll() {
return mManager.getDaoSession().loadAll(Father.class);
}
/**
* 根据主键id查询记录
*/
public Father queryItemById(long key) {
Father father = mManager.getDaoSession().load(Father.class, key);
return father;
}
/**
* 使用queryBuilder进行查询
*/
public List<Father> queryItemByQueryBuilder(long id) {
QueryBuilder<Father> queryBuilder = mManager.getDaoSession().queryBuilder(Father.class);
return queryBuilder.where(FatherDao.Properties._id.eq(id)).list();
}
/**
*关闭资源
*/
public void close() {
mManager.closeConnection();
}
}
在activity中调用:
调用插入:
switch (view.getId()) {
case R.id.insert:
for (int i = 1; i <= 10; i++) {
//插入一条记录
if (fatherDaoUtils.insert(new Father(Long.valueOf(i + ""), "demo" + i, 20))) {
Log.d("myGreenLog", "插入成功" + i);
}
}
break;
调用更新:
case R.id.update:
for (int i = 1; i <= 4; i++) {
//更新一条记录
if (fatherDaoUtils.updateFather(new Father(Long.valueOf(i + ""), "demo" + i, 20 + i))) {
Log.d("myGreenLog", "更新成功" + i);
}
}
break;
调用删除:
case R.id.delete:
for (int i = 1; i <= 2; i++) {
//删除一条记录
if (fatherDaoUtils.deleteFather(new Father(Long.valueOf(i + ""), "demo" + i, 20 + i))) {
Log.d("myGreenLog", "删除成功" + i);
}
}
break;
调用删除所有:
case R.id.deleteall:
//删除所有记录
fatherDaoUtils.deleteAll();
Log.i("myGreenLog", "删除成功");
break;
调用查询:
case R.id.selectItem:
for (int i = 1; i <= 10; i++) {
//查询一条记录
Father father = fatherDaoUtils.queryItemById(Long.valueOf(i + ""));
if (father != null) {
Log.d("myGreenLog", "查询成功" + father.toString());
} else {
Log.d("myGreenLog", "查询失败" + i);
}
}
break;
调用查询所有:
case R.id.selectAll:
Log.i("myGreenLog", fatherDaoUtils.queryAll().toString());
break;
调用queryBuilder查询:
case R.id.queryBuilder:
List<Father> List = fatherDaoUtils.queryItemByQueryBuilder(10);
for (Father father : List) {
Log.i("myGreenLog", father.toString());
}
break;