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)
 
  1. buildscript {
  2.     repositories {
  3.         jcenter()
  4.         mavenCentral() // add repository
  5.     }
  6.     dependencies {
  7.         classpath 'com.android.tools.build:gradle:2.3.2'
  8.         classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
  9.     }
  10. }
b、 配置依赖 ( Module:app  build.gradle  )
 
  1. apply plugin: 'com.android.application'
  2. apply plugin: 'org.greenrobot.greendao' // apply plugin
  3.  
  4. dependencies {
  5.     compile 'org.greenrobot:greendao:3.2.2' // add library
  6.  
  7.     // This is only needed if you want to use encrypted databases
  8.     compile 'net.zetetic:android-database-sqlcipher:3.5.6'//加密库依赖(可选项)
  9. }
c、 配置数据库相关信息 ( Module:app  build.gradle  )
 
  1. greendao {
  2.     schemaVersion 1 //数据库版本号
  3.     daoPackage 'com.speedystone.greendaodemo.db'// 设置DaoMaster、DaoSession、Dao 包名
  4.     targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录
  5. }
d、点击 : Sync Project with Gradle Files 按钮,同步一下工程 , 配置完成

    

五、快速入门

1, 我们写一个简单的实体类(User),测试一下

 
  1. package com.speedystone.greendaodemo.model;
  2.  
  3. import org.greenrobot.greendao.annotation.Entity;
  4. import org.greenrobot.greendao.annotation.Id;
  5.  
  6. /**
  7.  * Created by Speedy on 2017/6/30.
  8.  */
  9. @Entity
  10. public class User {
  11.  
  12.     @Id
  13.     private long id;
  14.  
  15.     private String name;
  16.  
  17.     private int age;
  18.  
  19.     //此处省略了getter,setter 方法
  20. }

2、点击 Make Project(或者 Make Moudle 'App') 编译一下工程 。如果配置正确,会在配置的包目录下自动会生成 DaoMaster,DaoSession 和 UserDao 类 。

3,初始化 GreenDao ( 通常初始化代码写在我们的 Application 类中)

4,获取 UserDao

 
  1.   MyApp myApp = (MyApp) getApplication();
  2.   DaoSession daoSession =  myApp.getDaoSession();
  3.   UserDao userDao = daoSession.getUserDao();

5, 保存记录

 
  1.  User user = new User();
  2.  user.setUserId(1);
  3.  user.setName("小明");
  4.  user.setAge(16);
  5.  
  6.   userDao.insert(user);
 
  1.  User user = new User();
  2.  user.setUserId(1);
  3.  user.setName("小明");
  4.  user.setAge(16);
  5.  
  6.  //插入或者替换
  7.  userDao.insertOrReplace(user);

5, 删除记录

 
  1. public void delete(User user){
  2.     userDao.delete(user);
  3. }

或者

 
  1. public void deleteByUserId(long userid){
  2.      userDao.deleteByKey(1L);
  3. }

6,更新记录

 
  1. public void update(User user){
  2.     userDao.update(user);
  3. }

7,查询记录

 
  1. public List query(){
  2.     return userDao.loadAll();// 查询所有记录
  3. }
 
  1. public User query2(){
  2.         return userDao.loadByRowId(1);//根据ID查询
  3. }
 
  1. public List query2(){
  2.         return userDao.queryRaw("where AGE>?","10");//查询年龄大于10的用户
  3. }
 
  1. //查询年龄大于10的用户
  2. public List query4(){
  3.     QueryBuilder builder = userDao.queryBuilder();
  4.     return  builder.where(UserDao.Properties.Age.gt(10)).build().list();
  5. }

六、注解详解

@Entity  

表明这个实体类会在数据库中生成一个与之相对应的表

属性:

  • schema:告知GreenDao当前实体属于哪个 schema

  • schema active:标记一个实体处于活跃状态,活动实体有更新、删除和刷新方法

  • nameInDb:在数据库中使用的别名,默认使用的是实体的类名,

  • indexes:定义索引,可以跨越多个列

  • createInDb:标记创建数据库表(默认:true)

  • generateConstructors  自动创建全参构造方法(同时会生成一个无参构造方法)(默认:true)

  • generateGettersSetters  自动生成 getters and setters 方法(默认:true)

 
  1. @Entity(
  2.         schema = "myschema",
  3.         active = true,
  4.         nameInDb = "AWESOME_USERS"
  5.         indexes = {
  6.                 @Index(value = "name DESC", unique = true)
  7.         },
  8.         createInDb = true,
  9.         generateConstructors = false,
  10.         generateGettersSetters = true
  11. )
  12. public class User {
  13.   ...
  14. }

@Id

对应数据表中的 Id 字段

@Index

使用@Index作为一个属性来创建一个索引,默认是使用字段名

 
  1. @Entity
  2. public class User {
  3.     @Id 
  4.     private Long id;
  5.  
  6.     @Index(unique = true)
  7.     private String name;
  8. }

@Property

设置一个非默认关系映射所对应的列名,默认是使用字段名,例如:@Property(nameInDb = "userName")

@NotNull  

设置数据库表当前列不能为空

@Transient

添加此标记后不会生成数据库表的列

@Unique

表名该属性在数据库中只能有唯一值

 
  1. @Entity
  2. public class User {
  3.     @Id 
  4.     private Long id;
  5.     @Unique
  6.     private String name;
  7. }

@ToOne

表示一对一关系

 
  1. @Entity
  2. public class Order {
  3.  
  4.     @Id private Long id;
  5.  
  6.     private long customerId;
  7.  
  8.     @ToOne(joinProperty = "customerId")
  9.     private Customer customer;
  10. }
  11.  
  12. @Entity
  13. public class Customer {
  14.     @Id 
  15.     private Long id;
  16. }

@OrderBy

更加某一字段排序 ,例如:@OrderBy("date ASC")

@ToMany

定义一对多个实体对象的关系

 
  1. @Entity
  2. public class Customer {
  3.     @Id private Long id;
  4.  
  5.     @ToMany(referencedJoinProperty = "customerId")
  6.     @OrderBy("date ASC")
  7.     private List orders;
  8. }
  9.  
  10. @Entity
  11. public class Order {
  12.     @Id private Long id;
  13.     private Date date;
  14.     private long customerId;
  15. }



六、实际项目中应用 

        
/**
 * 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);
    }

}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值