一、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 类 。
3,初始化 GreenDao ( 通常初始化代码写在我们的 Application 类中)
4,获取 UserDao
- MyApp myApp = (MyApp) getApplication();
- DaoSession daoSession = myApp.getDaoSession();
- UserDao userDao = daoSession.getUserDao();
5, 保存记录
- User user = new User();
- user.setUserId(1);
- user.setName("小明");
- user.setAge(16);
- userDao.insert(user);
- User user = new User();
- user.setUserId(1);
- user.setName("小明");
- user.setAge(16);
- //插入或者替换
- userDao.insertOrReplace(user);
5, 删除记录
- public void delete(User user){
- userDao.delete(user);
- }
或者
- public void deleteByUserId(long userid){
- userDao.deleteByKey(1L);
- }
6,更新记录
- public void update(User user){
- userDao.update(user);
- }
7,查询记录
- 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)
- @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
对应数据表中的 Id 字段
@Index
使用@Index作为一个属性来创建一个索引,默认是使用字段名
- @Entity
- public class User {
- @Id
- private Long id;
- @Index(unique = true)
- private String name;
- }
@Property
设置一个非默认关系映射所对应的列名,默认是使用字段名,例如:@Property(nameInDb = "userName")
@NotNull
设置数据库表当前列不能为空
@Transient
添加此标记后不会生成数据库表的列
@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
定义一对多个实体对象的关系
- @Entity
- public class Customer {
- @Id private Long id;
- @ToMany(referencedJoinProperty = "customerId")
- @OrderBy("date ASC")
- private List orders;
- }
- @Entity
- public class Order {
- @Id private Long id;
- private Date date;
- private long customerId;
- }
六、实际项目中应用
/** * Demo class * * @author yyd * @date 2018/2/28 * 将所有创建的表格相同的部分封装到这个BaseDao中 */ public class BaseDao<T> { public static final String TAG = BaseDao.class.getSimpleName(); public static final boolean DUBUG = true; public DaoManager manager; public DaoSession daoSession; public BaseDao(Context context) { manager = DaoManager.getInstance(); manager.init(context); daoSession = manager.getDaoSession(); manager.setDebug(DUBUG); } /**************************数据库插入操作***********************/ /** * 插入单个对象 * @param object * @return */ public boolean insertObject(T object){ boolean flag = false; try { flag = manager.getDaoSession().insert(object) != -1 ? true:false; } catch (Exception e) { Log.e(TAG, e.toString()); } return flag; } /** * 插入多个对象,并开启新的线程 * @param objects * @return */ public boolean insertMultObject(final List<T> objects){ boolean flag = false; if (null == objects || objects.isEmpty()){ return false; } try { manager.getDaoSession().runInTx(new Runnable() { @Override public void run() { for (T object : objects) { manager.getDaoSession().insertOrReplace(object); } } }); flag = true; } catch (Exception e) { Log.e(TAG, e.toString()); flag = false; }finally { // manager.CloseDataBase(); } return flag; } /**************************数据库更新操作***********************/ /** * 以对象形式进行数据修改 * 其中必须要知道对象的主键ID * @param object * @return */ public void updateObject(T object){ if (null == object){ return ; } try { manager.getDaoSession().update(object); } catch (Exception e) { Log.e(TAG, e.toString()); } } /** * 批量更新数据 * @param objects * @return */ public void updateMultObject(final List<T> objects, Class clss){ if (null == objects || objects.isEmpty()){ return; } try { daoSession.getDao(clss).updateInTx(new Runnable() { @Override public void run() { for(T object:objects){ daoSession.update(object); } } }); } catch (Exception e) { Log.e(TAG, e.toString()); } } /**************************数据库删除操作***********************/ /** * 删除某个数据库表 * @param clss * @return */ public boolean deleteAll(Class clss){ boolean flag = false; try { manager.getDaoSession().deleteAll(clss); flag = true; } catch (Exception e) { Log.e(TAG, e.toString()); flag = false; } return flag; } /** * 删除某个对象 * @param object * @return */ public void deleteObject(T object){ try { daoSession.delete(object); } catch (Exception e) { Log.e(TAG, e.toString()); } } /** * 异步批量删除数据 * @param objects * @return */ public boolean deleteMultObject(final List<T> objects, Class clss){ boolean flag = false; if (null == objects || objects.isEmpty()){ return false; } try { daoSession.getDao(clss).deleteInTx(new Runnable() { @Override public void run() { for(T object:objects){ daoSession.delete(object); } } }); flag = true; } catch (Exception e) { Log.e(TAG, e.toString()); flag = false; } return flag; } /**************************数据库查询操作***********************/ /** * 获得某个表名 * @return */ public String getTablename(Class object){ return daoSession.getDao(object).getTablename(); } // /** // * 查询某个ID的对象是否存在 // * @param // * @return // */ // public boolean isExitObject(long id,Class object){ // QueryBuilder<T> qb = (QueryBuilder<T>) daoSession.getDao(object).queryBuilder(); // qb.where(UserDao.Properties.Id.eq(id)); // long length = qb.buildCount().count(); // return length>0 ? true:false; // } /** * 根据主键ID来查询 * @param id * @return */ public T QueryById(long id,Class object){ return (T) daoSession.getDao(object).loadByRowId(id); } /** * 查询某条件下的对象 * @param object * @return */ public List<T> QueryObject(Class object, String where, String...params){ Object obj = null; List<T> objects = null; try { obj = daoSession.getDao(object); if (null == obj){ return null; } objects = daoSession.getDao(object).queryRaw(where,params); } catch (Exception e) { Log.e(TAG, e.toString()); } return objects; } /** * 查询所有对象 * @param object * @return */ public List<T> QueryAll(Class object){ List<T> objects = null; try { objects = (List<T>) daoSession.getDao(object).loadAll(); } catch (Exception e) { Log.e(TAG,e.toString()); } return objects; } /***************************关闭数据库*************************/ /** * 关闭数据库一般在Odestory中使用 */ public void CloseDataBase(){ manager.closeDataBase(); } }
/** * Demo class * * @author yyd * @date 2018/2/28 */ public class DaoUtils { private static NewsInfoManager newsInfoManager; public static Context context; private static CircleInfoManager circleInfoManager; public static void init(Context context) { DaoUtils.context = context.getApplicationContext(); } /** * 单列模式获取User对象 * * @return */ public static NewsInfoManager getNewsInfoManager() { if (newsInfoManager == null) { newsInfoManager = new NewsInfoManager(context); } return newsInfoManager; } public static CircleInfoManager getCircleInfoManager() { if (circleInfoManager == null) { circleInfoManager = new CircleInfoManager(context); } return circleInfoManager; } }
** * Demo class * * * @author yyd * @date 2018/2/28 * * * 进行数据库的管理 * 1.创建数据库 * 2.创建数据库表 * 3.对数据库进行增删查改 * 4.对数据库进行升级 */ public class DaoManager { private static final String TAG = DaoManager.class.getSimpleName(); private static final String DB_NAME="supervolleyball.db";//数据库名称 private volatile static DaoManager mDaoManager;//多线程访问 private static DaoMaster.DevOpenHelper mHelper; private static DaoMaster mDaoMaster; private static DaoSession mDaoSession; private static SQLiteDatabase db; private Context context; /** * 使用单例模式获得操作数据库的对象 * @return */ public static DaoManager getInstance(){ DaoManager instance = null; if (mDaoManager==null){ synchronized (DaoManager.class){ if (instance==null){ instance = new DaoManager(); mDaoManager = instance; } } } return mDaoManager; } /** * 初始化Context对象 * @param context */ public void init(Context context){ this.context = context; } /** * 判断数据库是否存在,如果不存在则创建 * @return */ public DaoMaster getDaoMaster(){ if (null == mDaoMaster){ mHelper = new DaoMaster.DevOpenHelper(context,DB_NAME,null); mDaoMaster = new DaoMaster(mHelper.getWritableDatabase()); } return mDaoMaster; } /** * 完成对数据库的增删查找 * @return */ public DaoSession getDaoSession(){ if (null == mDaoSession){ if (null == mDaoMaster){ mDaoMaster = getDaoMaster(); } mDaoSession = mDaoMaster.newSession(); } return mDaoSession; } /** * 设置debug模式开启或关闭,默认关闭 * @param flag */ public void setDebug(boolean flag){ QueryBuilder.LOG_SQL = flag; QueryBuilder.LOG_VALUES = flag; } /** * 关闭数据库 */ public void closeDataBase(){ closeHelper(); closeDaoSession(); } public void closeDaoSession(){ if (null != mDaoSession){ mDaoSession.clear(); mDaoSession = null; } } public void closeHelper(){ if (mHelper!=null){ mHelper.close(); mHelper = null; } } /** * 删除表 */ public void DeletDataBase(){ } }
/** * Demo class * * @author yyd */ public class NewsInfoManager extends BaseDao<NewsBean> { public NewsInfoManager(Context context) { super(context); } /***************************数据库查询*************************/ /** * 通过ID查询对象 * @param id * @return */ private NewsBean loadById(long id){ return daoSession.getNewsBeanDao().load(id); } /** * 获取某个对象的主键ID * @param user * @return */ private long getID(NewsBean user){ return daoSession.getNewsBeanDao().getKey(user); } /** * 通过ID获取User对象 * @return */ private List<NewsBean> getNewsById(int key){ QueryBuilder queryBuilder = daoSession.getNewsBeanDao().queryBuilder(); queryBuilder.where(NewsBeanDao.Properties.News_id.eq(key)); int size = queryBuilder.list().size(); if (size > 0){ return queryBuilder.list(); }else{ return null; } } /** * 通过id获取Customer对象 * @return */ public List<Long> getIdByName(int key){ List<NewsBean> newsBeans = getNewsById(key); List<Long> ids = new ArrayList<Long>(); int size = newsBeans.size(); if (size > 0){ for (int i = 0;i < size;i++){ ids.add(newsBeans.get(i).getId()); } return ids; }else{ return null; } } /** * 通过分页查询数据查找数据 根据条件查找 ,排序 * @return */ public List<NewsBean> GetAllList(int offset,int classifyid){ QueryBuilder queryBuilder = daoSession.getNewsBeanDao().queryBuilder().where(NewsBeanDao.Properties.Classifyid.eq(classifyid)).offset(10*(offset-1)).limit(10).orderDesc(NewsBeanDao.Properties.Id); int size = queryBuilder.list().size(); if (size > 0){ return queryBuilder.list(); }else{ return null; } } /** * 根据新闻修改评论数 * @param newsId * @param comment_number */ public void UpDateNewsComment(int newsId,int comment_number){ QueryBuilder queryBuilder = daoSession.getNewsBeanDao().queryBuilder().where(NewsBeanDao.Properties.News_id.eq(newsId)); List<NewsBean> list = queryBuilder.list(); if (list!=null){ for (int i = 0; i <list.size() ; i++) { NewsBean newsBean = list.get(i); newsBean.setComment_number(comment_number); daoSession.getNewsBeanDao().update(newsBean); } } } /***************************数据库删除*************************/ /** * 根据ID进行数据库的删除操作 * @param newsId * @param classifyid */ public void deleteById(int newsId,int classifyid){ QueryBuilder<NewsBean> qb = daoSession.getNewsBeanDao().queryBuilder(); DeleteQuery<NewsBean> bd = qb.where(NewsBeanDao.Properties.News_id.eq(newsId),NewsBeanDao.Properties.Classifyid.eq(classifyid)).buildDelete(); bd.executeDeleteWithoutDetachingEntities(); } /** * 根据ID同步删除数据库操作 * @param ids */ private void deleteByIds(List<Long> ids){ daoSession.getNewsBeanDao().deleteByKeyInTx(ids); } }