GreenDao使用指南

简介

greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。采用编译时注解的方式,对与编译时注解和运行时注解的优缺点可以做一个了解。
greenDAO优点:性能最大化,可能是Android平台上最快的ORM框架;易于使用的API;最小的内存开销;依赖体积小;支持数据库加密;强大的社区支持;

一,配置

1, 在根目录的build.gradle添加

buildscript {
    repositories {
        jcenter()
        //添加仓库
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.2'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
    }
}

2, 在app的build.gradle添加

apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao'
dependencies {
    implementaion 'org.greenrobot:greendao:3.2.2'
}

3,配置数据库版本和类生成目录,在app的 build.gradle 添加

 greendao {
        schemaVersion 1//数据库版本号
        daoPackage 'com.xiaoyehai.landsurvey.greendao'//设置DaoMaster、DaoSession、Dao包名
        targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录
 }

二,demo中使用

1,创建实体类

在这里插入图片描述点击build gradle生成相关代码以及类,DaoMaster、DaoSession、XXXDao。
在这里插入图片描述
2, 简单封装

1,DBManager数据库管理

public class DBManager {
    private static final String DB_NAME = "launcher.db";//数据库名称
    private volatile static DBManager mDaoManager;
    private OpenHelper mHelper;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private DBManager() {
        mHelper = new OpenHelper(LauncherApplication.getApplication(), DB_NAME);
        mDaoMaster = new DaoMaster(mHelper.getWritableDb());
        mDaoSession = mDaoMaster.newSession();
    }

    public static DBManager getInstance() {
        if (mDaoManager == null) {
            synchronized (DBManager.class) {
                if (mDaoManager == null) {
                    mDaoManager = new DBManager();
                }
            }
        }
        return mDaoManager;
    }

    public DaoSession getDaoSession() {
        return mDaoSession;
    }
}

2,OpenHelper数据库升级管理(数据库升级会删除表数据,重新创建,对于数据库数据恢复需要单独编写OpenHelper去管理)

public class OpenHelper extends DaoMaster.OpenHelper {
    public OpenHelper(Context context, String name) {
        super(context, name);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        //把需要管理的数据库表DAO作为最后一个参数传入到方法中
        Log.e("OpenHelper", "onUpgrade: oldVersion=" + oldVersion + ",newVersion=" + newVersion);
        MigrationHelper.getInstance().migrate(db, UserDao.class);
    }
}

3,MigrationHelper真正实现数据库升级恢复数据

public class MigrationHelper {

    private volatile static MigrationHelper instance;

    public static MigrationHelper getInstance() {
        if (instance == null) {
            instance = new MigrationHelper();
        }
        return instance;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }

    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");

            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tableName).append(";");

            db.execSQL(insertTableStringBuilder.toString());
        }
    }

    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList();

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tempTableName).contains(columnName)) {
                    properties.add(columnName);
                }
            }

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();

            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);

            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class)) {
            return "BOOLEAN";
        }
        return "";
    }

    private static List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }
}

4,如何调用增删改查实现数据操作

DBManager.getInstance().getDaoSession().insert(object)
DBManager.getInstance().getDaoSession().delete(object)
DBManager.getInstance().getDaoSession().update(object)
DBManager.getInstance().getDaoSession().loadAll(object)

另外还有一种调用方式,可以通过XXXDao类去调用,这种方式更加灵活,此类中有更多的方式。

5,增删改查操作类可以单独写,更方便管理

首先写个基类,提供最基本的方法

public abstract class BaseImpl<T> {
    public DaoSession daoSession;

    public BaseImpl() {
        if (daoSession == null) {
            daoSession = DBManager.getInstance().getDaoSession();
        }
    }

    /**
     * 插入一条数据
     */
    public abstract void insert(T object);

    /**
     * 更新一条数据
     */
    public abstract void update(T object);

    /**
     * 查询所有
     *
     * @return
     */
    public abstract List<T> loadAll();

    /**
     * 删除
     *
     * @return
     */
    public abstract void delete(T object);

}

UserImpl实现基类,在这里可以操作更多方式。

public class UserImpl extends BaseImpl<User> {
    public UserImpl () {
        super();
    }

    @Override
    public void insert(User object) {
        daoSession.insert(object);
    }

    @Override
    public void update(User object) {
        daoSession.update(object);
    }

    @Override
    public List<User> loadAll() {
        return daoSession.loadAll(User.class);
    }
    

    @Override
    public void delete(Userobject) {
        daoSession.delete(object);
    }

    /**
     * 根据名字查询
     *
     * @param name
     * @return
     */
    public List<User> loadAllByName(String name) {
        QueryBuilder<User> queryBuilder = daoSession.queryBuilder(User.class);
        return queryBuilder.where(UserDao.Properties.Name.eq(name)).list();
    }
    
   /**
     * 用UserDao插入列表数据
     * @param list
     */
    public void insert(List<User> list){
        daoSession.getUserDao().insertInTx(list);
    }
}

三,基本介绍

1, GreenDao 的核心类
GreenDao 的核心类有三个:分别是 DaoMaster,DaoSession,XXXDao,这三个类都会自动创建,无需自己编写创建!

  • DaoMaster::DaoMaster 保存数据库对象(SQLiteDatabase)并管理特定模式的 DAO
    类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类 OpenHelper 和DevOpenHelper 是
    SQLiteOpenHelper 实现,它们在 SQLite 数据库中创建模式。
  • DaoSession:管理特定模式的所有可用 DAO 对象,您可以使用其中一个getter方法获取该对象。DaoSession还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。
  • XXXDao:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO 生成DAO。它具有比 DaoSession更多的持久性方法,例如:count,loadAll 和 insertInTx。
  • Entities :可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。

2, 实现增删改查

增:daoSession.insert(bean),daoSession.insertOrReplace(bean)
删:delete和deleteAll();
改:updata()
查:loadAll()查询所有,queryRaw()根据条件查询,queryBuilder()更方便的查询
通过daoSession.getXXXDao().方法,这种有更多用法。

3, QueryBuilder的使用
①,QueryBuilder 的常见方法:

  • where(WhereCondition cond, WhereCondition… condMore): 查询条件,参数为查询的条件!
  • or(WhereCondition cond1, cond2, WhereCondition…condMore): 嵌套条件或者,用法同 or。
  • and(WhereCondition cond1, cond2, WhereCondition… condMore): 嵌套条件且,用法同and。
  • join(Property sourceProperty, ClassdestinationEntityClass):多表查询,后面会讲。
  • 输出结果有四种方式,选择其中一种最适合的即可,list()返回值是 List,而其他三种返回值均实现
    Closeable,需要注意的不使用数据时游标的关闭操作
  • list ()所有实体都加载到内存中。结果通常是一个没有魔法的 ArrayList。最容易使用。
  • listLazy ()实体按需加载到内存中。首次访问列表中的元素后,将加载并缓存该元素以供将来使用。必须关闭。
  • listLazyUncached ()实体的“虚拟”列表:对列表元素的任何访问都会导致从数据库加载其数据。必须关闭。
  • listIterator ()让我们通过按需加载数据(懒惰)来迭代结果。数据未缓存。必须关闭。

②,使用QueryBuilder进行查询操作

根据name查询,orderAsc()升序
在这里插入图片描述
取10条 Id 大于1的数据,且偏移2条
在这里插入图片描述
4, 注解

基础属性注解(@Id,@Property,@NotNull,@Transient)

  • @Id:@Id注解选择 long / Long属性作为实体 ID。在数据库方面,它是主键。参数autoincrement = true表示自增,id 不给赋值或者为赋值为 null 即可(这里需要注意,如果要实现自增,id 必须是 Long,为 long 不行!)。
  • @Property:允许您定义属性映射到的非默认列名。如果不存在,GreenDAO 将以 SQL-ish 方式使用字段名称(大写,下划线而不是 camel 情况,例如 name 将成为 NAME)。注意:您当前只能使用内联常量来指定列名。
  • @NotNull:设置数据库表当前列不能为空 。
  • @Transient:添加次标记之后不会生成数据库表的列。标记要从持久性中排除的属性。将它们用于临时状态等。或者,您也可以使用 Java 中的 transient 关键字。

索引注解

@Index:使用@Index 作为一个属性来创建一个索引,通过 name 设置索引别名,也可以通过unique给索引添加约束。
@Unique:向索引添加 UNIQUE 约束,强制所有值都是唯一的。

关系注解

关系型注解 GreenDao 中主要就两个:
@ToOne:定义与另一个实体(一个实体对象)的关系
@ToMany:定义与多个实体对象的关系

五, 关系表的创建

1, 一对一关系,每个用户对应一个用户信息
使用注解@ToOne(joinProperty = “id”)
用户类
在这里插入图片描述
用户信息类
用户信息类
插入数据
在这里插入图片描述
2, 一对多关系,一个领导对应多名员工

使用注解@ToMany(referencedJoinProperty = “id”)
在这里插入图片描述
在这里插入图片描述
插入数据
在这里插入图片描述
3, 多对多关系,一个老师对应多个学生,一个学生对应多个老师

使用注解@JoinEntity(entity = TeacherJoinStudentBean.class,sourceProperty = “tId”,
targetProperty = “sId”)
在这里插入图片描述在这里插入图片描述在这里插入图片描述
插入数据,需要注意这里insertInTx()方法,不能直接用daoSession调用。需要调用getXXXDao,通过Dao调用。另外XXXDao中也有save()的用法
在这里插入图片描述

六, 数据库加密

1, 导入加密库文件

implementation ‘net.zetetic:android-database-sqlcipher:3.5.6’
修改 DaoSession 的生成方式
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值