GreenDao 使用详解(入门篇)
Android ORM 框架:GreenDao 使用详解
- 最近太忙了,直接引用网上的图片
一、GreenDao 简介
greenDAO 是一款开源的面向 Android 的轻便、快捷的 ORM 框架,将 Java 对象映射到 SQLite 数据库中,我们操作数据库的时候,不在需要编写复杂的 SQL语句, 在性能方面,greenDAO 针对 Android 进行了高度优化, 最小的内存开销 、依赖体积小 同时还是支持数据库加密。
greenDAO 官网地址:http://greenrobot.org/greendao/
二、GreenDao 特征:
1、对象映射( ORM)
- greenDAO 是ORM 框架,可以非常便捷的将Java 对象映射到 SQLite 数据库中保存。
2、高性能
- ORM 框架有很多,比较著名的有 OrmLite , ActiveAndroid 等,性能也不一样,下图是 GreenDao 官方给出的性能对比。
3、支持加密
- GreenDao 是支持加密的,可以安全的保存用户数据。
4、轻量级
- GreenDao 核心库小于100k ,所以我们并不会担心添加 GreenDao 后 APK 大小会变的是否庞大。
5、支持 protocol buffer(protobuf) 协议
- GreenDao 支持 protocol buffer(protobuf) 协议数据的直接存储,如果你通过 protobuf 协议与服务器交互,将不需要任何的映射。
6,代码生成
- greenDAO 会根据配置信息自动生成核心管理类以及 DAO 对象
7,开源
- greenDAO 是开源的,我们可以在github 上下载源码,学习。github 地址:https://github.com/greenrobot/greenDAO
三、核心类介绍
DaoMaster:
- 使用 greenDAO 的入口点。DaoMaster 负责管理数据库对象(SQLiteDatabase)和 DAO 类(对象),我们可以通过它内部类 OpenHelper 和 DevOpenHelper SQLiteOpenHelper 创建不同模式的 SQLite 数据库。
DaoSession :
- 管理指定模式下的所有 DAO 对象,DaoSession提供了一些通用的持久性方法比如插入、负载、更新、更新和删除实体。
XxxDAO :
- 每个实体类 greenDAO 多会生成一个与之对应DAO对象,如:User 实体,则会生成一个一个UserDao 类
Entities
- 可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。
核心类之间的关系
四、 集成 GreenDAO
a、设置仓库与插件(Project: build.gradle)
buildscript { repositories { jcenter() mavenCentral() // add repository } dependencies { classpath 'com.android.tools.build:gradle:2.3.2' classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin } }
b、 配置依赖 ( Module:app build.gradle )
apply plugin: 'com.android.application' apply plugin: 'org.greenrobot.greendao' // apply plugin dependencies { compile 'org.greenrobot:greendao:3.2.2' // add library // This is only needed if you want to use encrypted databases compile 'net.zetetic:android-database-sqlcipher:3.5.6'//加密库依赖(可选项) }
c、 配置数据库相关信息 ( Module:app build.gradle )
greendao { schemaVersion 1 //数据库版本号 daoPackage 'com.speedystone.greendaodemo.db'// 设置DaoMaster、DaoSession、Dao 一般包名+文件夹名 targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录 文件生成的目录,相当于父级目录 }
d、点击 : Sync Project with Gradle Files 按钮,同步一下工程 , 配置完成
五、快速入门
1, 我们写一个简单的实体类(User),测试一下
package com.speedystone.greendaodemo.model; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; /** * Created by Speedy on 2017/6/30. */ @Entity public class User { @Id private long id; private String name; private int age; //此处省略了getter,setter 方法 }
2、点击 Make Project(或者 Make Moudle ‘App’) 编译一下工程 。如果配置正确,会在配置的包目录下自动会生成 DaoMaster,DaoSession 和 UserDao 类 。(没有对应文件产生式可以重启一下Androidstudio)
3,初始化 GreenDao ( 通常初始化代码写在我们的 Application 类中)
public class MApplication extends android.support.multidex.MultiDexApplication { private DaoSession daoSession; @Override public void onCreate() { super.onCreate(); initDreenDao(); } /** * greendao数据库初始化 */ private void initDreenDao() { DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "zbc_test.db"); SQLiteDatabase db = devOpenHelper.getWritableDatabase(); DaoMaster daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); } /** * 获取 DaoSession * * @return */ public DaoSession getDaoSession() { return daoSession; } }
4,获取 UserDao
MyApp myApp = (MyApp) getApplication(); DaoSession daoSession = myApp.getDaoSession(); UserDao userDao = daoSession.getUserDao();
5, 保存记录
5.1插入记录到数据库,id重复时不修改,会抛出异常,注意捕获
User user = new User(); user.setUserId(1); user.setName("小明"); user.setAge(16); userDao.insert(user);
5.2插入记录到数据库,id重复时直接替换
User user = new User(); user.setUserId(1); user.setName("小明"); user.setAge(16); //插入或者替换 userDao.insertOrReplace(user);
6, 删除记录
public void delete(User user){ userDao.delete(user); }
或者
public void deleteByUserId(long userid){ userDao.deleteByKey(1L); }
7,更新记录
public void update(User user){ userDao.update(user); }
8,查询记录
public List query(){ return userDao.loadAll();// 查询所有记录 } public User query2(){ return userDao.loadByRowId(1);//根据ID查询 } public List query2(){ return userDao.queryRaw("where AGE>?","10");//查询年龄大于10的用户 } //查询年龄大于10的用户 public List query4(){ QueryBuilder builder = userDao.queryBuilder(); return builder.where(UserDao.Properties.Age.gt(10)).build().list(); }
六、注解详解
名称 | 作用 |
---|---|
@Entity | 表明这个实体类会在数据库中生成一个与之相对应的表 |
schema | 告知GreenDao当前实体属于哪个 schema |
schema active | 标记一个实体处于活跃状态,活动实体有更新、删除和刷新方法 |
nameInDb | 在数据库中使用的别名,默认使用的是实体的类名, |
indexes | 定义索引,可以跨越多个列 |
createInDb | 标记创建数据库表(默认:true) |
generateConstructors | 自动创建全参构造方法(同时会生成一个无参构造方法)(默认:true) |
generateGettersSetters | 自动生成 getters and setters 方法(默认:true) |
@Id | 对应数据表中的 Id 字段 |
@Index | 使用@Index作为一个属性来创建一个索引,默认是使用字段名 |
@Property | 设置一个非默认关系映射所对应的列名,默认是使用字段名,例如:@Property(nameInDb = “userName”) |
@NotNull | 设置数据库表当前列不能为空 |
@Transient | 添加此标记后不会生成数据库表的列 |
@Unique | 表名该属性在数据库中只能有唯一值 |
@ToOne | 表示一对一关系 |
@OrderBy | 更加某一字段排序 ,例如:@OrderBy(“date ASC”) |
@ToMany | 定义一对多个实体对象的关系 |
@Entity
@Entity( schema = "myschema", active = true, nameInDb = "AWESOME_USERS", indexes = { @Index(value = "name DESC", unique = true) }, createInDb = true, generateConstructors = false, generateGettersSetters = true ) public class User { ... }
@Id 、@Index
@Entity public class User { @Id private Long id; @Index(unique = true) private String name; }
@Unique 表名该属性在数据库中只能有唯一值
@Entity public class User { @Id private Long id; @Unique private String name; }
@ToOne 表示一对一关系
@Entity public class Order { @Id private Long id; private long customerId; @ToOne(joinProperty = "customerId") private Customer customer; } @Entity public class Customer { @Id private Long id; }
@OrderBy 更加某一字段排序 ,例如:@OrderBy(“date ASC”)
@ToMany 定义一对多个实体对象的关系
@Entitypublic class Customer { @Id private Long id; @ToMany(referencedJoinProperty = "customerId") @OrderBy("date ASC") private List orders;}@Entitypublic class Order { @Id private Long id; private Date date; private long customerId;}
下面总结里一些GreenDao的使用心得
使用 .insert(userEntity); 方法时候报错,APP直接的崩溃闪退
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: USER_ENTITY._id (Sqlite code 1555), (OS error - 2:No such file or directory)
如图:
最终解决
可能发生这种BUG的两种情况
1:定义的字段为NOT NULL,而插入时对应的字段为NULL
2:你定义的自动为PRIMARY,而插入时想插入的值已经在表中存在。
针对情况2,建议用replace代替insert
通过这一点可以看出一个应用的场景:
1.如果不希望新增的数据替换相同key值的已有数据,我们可以采用 insert 方法
2.如果希望新来得数据无论如何也会替换相同key值的旧数据,应当使用 replace 方法
更多相关文章
- 每天学习一个Android中的常用框架——3.OkHttp
- Android(安卓)Studio环境下连接远程服务器中的sqlserver2012数据
- Android动态模糊效果的快速实现方法
- Android(安卓)基础总结:( 十六)Android(安卓)Thread
- Android(安卓)IPC系列--序列化机制
- Android—设计模式原则及常见的设计模式
- 自定义对象的监听方式
- Android的事件机制
- Android中 Intent/Bundle传递对象取值为null的剖析以及Serializa