Android中关系型数据库 GreenDao 3.2.2的使用

文章参考自:老罗GreenDao数据库课程以及 Nate - Android框架-GreenDao

前言

  1. android中的数据存储:
    网络存储
    数据库存储
    SharedPreference 存储
    ContentProvider存储
    文件存储

  2. GreenDao简介:
    是一款优秀的ORM框架(Object Relational Mapping)
    对象关系映射,其思想将关系数据库中表的数据映射成为对象。程序员就可以将对数据库的操作转化为对对象的操作。其目的是让程序员以面向对象的思想来实现对数据库的操作。
    是对SQlite数据库的封装

  3. 优秀的ORM框架还有
    OrmLite 、 SugarOrm 、 LitePal 、 GreenDao

  4. 关系型数据库Sql和非关系型数据库NoSql
    关系型数据库最典型的数据结构是表,是由二维表及其之间的联系说组成的一个数据组织,代表数据库是MySql、Oracle
    非关系型数据库严格上不是一种数据库,是一种数据结构化存储方法的集合,可以是文档或者是键值对等,代表数据库是MongoDB、Redis

  5. Android原生Api操作数据库有什么不便
    要手动拼装SQL
    要自己写操作数据库的常规代码
    不能自动把数据库中的数据映射
    没有实现级联查询

  6. 为什么要选择GreenDao
    性能、文档、流行性、上手方便、拓展性

  7. GreenDao资料查询地址
    GreenDao的Github地址: https://github.com/greenrobot/greenDAO
    GreenDao官网: http://greenrobot.org/greendao/
    GreenDao Api地址: http://greenrobot.org/files/greendao/javadoc/current/

使用

  1. GreenDao依赖配置:
// 在project的build.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
    }
}

// 在module的build.gradle中配置:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
 
dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // add library
}
  1. GreenDao混续配置:
-keep class org.greenrobot.greendao.**{*;}
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
    public static java.lang.String TABLENAME;
}
-keep class **$Properties
-keep public interface org.greenrobot.greendao.**
-keep class net.sqlcipher.database.**{*;}
-keep public interface net.sqlcipher.database.**
-dontwarn net.sqlcipher.database.**
-dontwarn org.greenrobot.greendao.**
-dontwarn rx.**
  1. GreenDao版本配置:
// module的build.gradle中配置greendao版本号和数据库目录
android{
    greendao{
        // 设置数据库版本号
        schemaVersion 1
        // 设置自动生成的数据库文件目录
        targetGenDir 'src/main/java'
        // 设置自动生成的数据库文件包名
        daoPackage 'test.zhr.com.greendaodemo.auto'
    }
}

上面配好之后,自己创建一个实体类,这个实体类对应的就是数据库中的一个表,实体类中的每一个字段,就对应表中的每一个字段。
实体类创建完后,添加一些注解,在id上添加 @Id(autoincrement = true) 注解,在实体类上添加 @Entity 注解
点击 Build—Make Project 生成需要自动生成的文件,生成的三个类在module的build.gradle中配置的daoPackage 目录下,这三个类如下: xxx(实体类名)Dao 、DaoMaster 、DaoSession。
注意:为了解决

API 'variant.getJavaCompiler()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'. It will be removed at the end of 2019

配置的targetGenDir可以注释掉,如果不注释的话自动生成的数据库文件会在app/src/main/java/test/zhr/com/greendaodemo/auto文件夹下
删除的话 则会生成在默认目录app/build/generated/sourse/greendao/test/zhr/com/greendaodemo/auto文件夹下

DaoMaster是GreenDao的总入口,负责DaoSession的创建和整个库的运行
DaoSession会话层,操作具体的Dao对象,包括Dao对象的注册。提供了基本的持久化方法,比如实体对象的insert、load、update、delete操作
xxxDao 生成的Dao对象,它提供比DaoSession更具体的方法,比如count、loadAll和insertInTx等
xxxEntity 实体类,和表中的字段一一对应

具体的流程:
DaoMaster----create—DaoSession—create&manage—xxxDao—load&save—xxxEntity

二次封装

主要是封装了Dao的管理类和Dao的工具类以及GreenDao数据库的升级及加密

// DaoManager

package com.zhr.test.dao;

import android.content.Context;
import com.zhr.test.auto.DaoMaster;
import com.zhr.test.auto.DaoSession;
import org.greenrobot.greendao.query.QueryBuilder;

public class DaoManager {

    private static final String DB_NAME = "student.sqlite";
    private volatile static DaoManager mDaoManager;
    private MyGreenDaoOpenHelper mHelper;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private Context mContext;

    /**
     * 私有构造方法,不让其通过构造创建对象
     */
    private DaoManager(){}

    /**
     * 使用单例模式获取操作数据对象
     * @return
     */
    public static DaoManager getInstance(){
        DaoManager instance = null;
        if(null == mDaoManager){
            synchronized (DaoManager.class){
                if(null == instance){
                    instance = new DaoManager();
                    mDaoManager = instance;
                }
            }
        }
        return mDaoManager;
    }

    /**
     * 获取上下文对象
     * @param context
     */
    public void initContext(Context context){
        this.mContext = context;
    }

    /**
     * 判断数据库是否存在 不存在则创建
     * @return
     */
    public DaoMaster getDaoMaster(){
        if(null == mDaoMaster){
            mHelper = new MyGreenDaoOpenHelper(mContext, DB_NAME, null);
            mDaoMaster = new DaoMaster(mHelper.getWritableDb());
//            mDaoMaster = new DaoMaster(mHelper.getEncryptedWritableDb(DeviceUtils.getUniqueDeviceId()));
        }
        return mDaoMaster;
    }

    /**
     * 完成对数据库的增删改查
     * @return
     */
    public DaoSession getDaoSession(){
        if(null == mDaoSession){
            if(null == mDaoMaster){
                mDaoMaster = getDaoMaster();
            }
            mDaoSession = mDaoMaster.newSession();
        }
        return mDaoSession;
    }

    /**
     * 打开数据库调试日志 默认是关闭的
     */
    public void setDebug(){
        QueryBuilder.LOG_SQL = true;
        QueryBuilder.LOG_VALUES = true;
    }

    /**
     * 数据库开启 使用完毕一定要关闭
     */
    public void closeDb(){
        closeHelper();
        closeDaoSession();
    }

    private void closeHelper(){
        if(null != mHelper){
            mHelper.close();
            mHelper = null;
        }
    }

    private void closeDaoSession(){
        if(null != mDaoSession){
            mDaoSession.clear();
            mDaoSession = null;
        }
    }
}

---------------------------------------------------------------------------------------------

// DaoUtils

package com.zhr.test.dao;

import android.content.Context;
import com.zhr.test.auto.StudentDao;
import com.zhr.test.entity.Student;
import org.greenrobot.greendao.query.QueryBuilder;
import org.greenrobot.greendao.query.WhereCondition;
import java.util.ArrayList;
import java.util.List;

/**
 * 完成对Student表的具体操作
 * insert、insertOrReplace、save、update的区别
 * insert 插入的对象id必须唯一,在id重复的时候插入会异常
 * update 根据id去更新数据,id重复则更新,不重复不更新
 * insertOrReplace 插入的对象id可以不唯一,id重复时会更新数据,没有重复时则插入
 * save insert或者update 根据id去更新数据,id重复则更新,不重复-如果手动指定则不更新
 * (一般也不会手动指定),不重复-自动生成则插入
 *
 * insertOrReplace以及save的使用场景分析
 * save:本地数据库提交数据给线上数据库,id是由本地数据库生成的,不会出现没有id的情况,使用save更高效,其他情况一律使用insertOrReplace
 * insertOrReplace:线上数据库同步数据到本地数据库,用的是线上数据库的id,使用insertOrReplace
 * 综上,如果id在本地生成,绝对存在的情况使用save;不保证绝对存在使用insertOrReplace
 */
public class DaoUtils {

    private DaoManager mDaoManager;

    public DaoUtils(Context context){
        mDaoManager = DaoManager.getInstance();
        mDaoManager.initContext(context);
        mDaoManager.setDebug();
    }

    /**
     * 插入一条数据
     * @param object
     * @return
     */
    public boolean insert(Object object){
        boolean flag = false;
        try {
            flag = mDaoManager.getDaoSession().insertOrReplace(object) != -1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 插入多条数据,需要开辟新的线程
     * @param objects
     * @return
     */
    public boolean insertMult(final List<?> objects){
        boolean flag = false;
        try {
            mDaoManager.getDaoSession().runInTx(new Runnable() {
                @Override
                public void run() {
                    for(Object object : objects){
                        if(object instanceof Student){
                            mDaoManager.getDaoSession().insertOrReplace(object);
                        }
                    }
                }
            });
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 保存一条数据
     * 比较save和insertOrReplace的区别
     * @param student
     * @return
     */
    public boolean save(Student student){
        boolean flag = false;
        try {
            mDaoManager.getDaoSession().getStudentDao().save(student);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 保存多条数据
     * 比较save和insertOrReplace的区别
     * @param students
     * @return
     */
    public boolean saveMult(List<Student> students){
        boolean flag = false;
        try {
            for(Student student : students) {
                mDaoManager.getDaoSession().getStudentDao().saveInTx(student);
            }
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 根据主键删除一条数据
     * 若id未找到则不会删除数据 若找到则会删除数据
     * @param object
     * @return
     */
    public boolean deleteById(Object object){
        boolean flag = false;
        try {
            mDaoManager.getDaoSession().delete(object);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 删除表中的所有数据
     * @return
     */
    public boolean deleteAll(Class<?> entityClass){
        boolean flag = false;
        try {
            mDaoManager.getDaoSession().deleteAll(entityClass);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 根据主键更新一条数据
     * 若id未找到则不会更新数据 若找到则会更新数据
     * @param object
     * @return
     */
    public boolean updateById(Object object){
        boolean flag = false;
        try {
            mDaoManager.getDaoSession().update(object);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 根据id查找一条数据 没有查到会异常
     * @param entityClass
     * @param id
     * @return
     */
    public Object quaryById(Class<?> entityClass , Long id){
        return mDaoManager.getDaoSession().load(entityClass , id);
    }

    /**
     * 查找表中的所有数据
     * @param entityClass
     * @return
     */
    public List<?> quaryAll(Class<?> entityClass){
        return mDaoManager.getDaoSession().loadAll(entityClass);
    }

    /**
     * QueryBuilder中的查询语句
     * where             使用and连接多个查询条件,返回的是数据
     * whereor           使用or连接多个查询条件,返回的是数据
     * and               使用and构成多个查询条件,返回的是查询条件
     * or                使用or构成多个查询条件,返回的是查询条件
     * orderAsc          以字段升序排列 不要以String类型的参数进行排序
     * orderDesc         以字段降序排列
     * orderCustom       自定义排序,根据属性和排序方案进行排序
     * orderRaw          自定义排序,用SQL语句进行排序
     * list              返回满足查询条件的结果集,如果有多条则无法查出并且报错
     * lazyList          懒加载集合,使用时才加载,一般在多表级联查询时效果明显。源码使用了锁机制,完善了多线程并发的操作
     * listIterator      使用迭代器遍历集合数据
     * count             结果集的数量
     * unique            返回唯一结果或者null
     * distinct          过滤掉重复字段(感觉无效)
     * offset            每次的偏移量,配合limit使用
     * limit             限制的数量
     *
     * eq                等于xx
     * gt                大于xx
     * ge                大于等于xx
     * lt                小于xx
     * le                小于等于xx
     * between           [xx , xx]区间值
     * in                等于xx或者等于xx
     * like              根据关键字模糊查询xx,模糊查询的关键字前后需要加%xx%
     * notEq             不等于xx
     * notIn             不等于xx或者不等于xx,注意如果只传入一个值的时候和notEq意思一样
     * isnull            为空
     * isNotNull 不为空
     *
     * 查找表中的数据集
     * @param entityClass
     * @return
     */
    public QueryBuilder<?> quaryList(Class<?> entityClass){
        return mDaoManager.getDaoSession().queryBuilder(entityClass);
    }

    /******************************不常用  功能测试的方法*******************************/

    public List<Student> builderQuary(Class<Student> entityClass){
        QueryBuilder<Student> builder = mDaoManager.getDaoSession().queryBuilder(entityClass);
        // 查询年龄大于等于25的数据条数
//        long count = builder.where(StudentDao.Properties.Age.ge(25)).count();
        // 查询年龄大于等于25或者小于等于20的数据条数
//        long count = builder.whereOr(StudentDao.Properties.Age.ge(25), StudentDao.Properties.Age.le(20)).count();
        // 查询年龄在[20 , 25]之间的数据条数
//        long count = builder.where(StudentDao.Properties.Age.between(20, 25)).count();
        // 查询年龄为20或者为25的数据条数
//        long count = builder.where(StudentDao.Properties.Age.in(20, 25)).count();
        // 查询年龄为20或者为25的数据条数
//        long count = builder.whereOr(StudentDao.Properties.Age.eq(20), StudentDao.Properties.Age.eq(25)).count();
        // 使用模糊查询必须把要查询的内容百分号包裹
        // 查询地址中带有京字的数据条数
//        long count = builder.where(StudentDao.Properties.Address.like("京")).count();
        // 查询年龄为20或者为25的数据条数
//        WhereCondition or = builder.or(StudentDao.Properties.Age.eq(20), StudentDao.Properties.Age.eq(25));
//        long count = builder.where(or).count();
        // 查询年龄为19的唯一一条数据,如果有多条则无法查出并且报错
//        Student unique = builder.where(StudentDao.Properties.Age.eq(19)).build().unique();
        long count = builder.where(StudentDao.Properties.Age.eq(19)).buildCount().count();
        return new ArrayList<>();
    }

    /**
     * 原生sql语句查找数据
     * 若未查找到的话 则不会返回数据
     * @param entityClass
     * @return
     */
    public List<Student> nativeQuary(Class<Student> entityClass){
//        return mDaoManager.getDaoSession().queryRaw(entityClass, "where name like ? and _id > ?",new String[]{"%李%" , "1"});
        return mDaoManager.getDaoSession().queryBuilder(entityClass).where(new WhereCondition.StringCondition(
                // 在Student表中根据外键idNo查询idCard表中大于100岁的身份证属于哪个派出所
                "ID_NO IN " + "(SELECT ID_NO FROM ID_CARD WHERE AGE > 100)")).list();
    }
}

数据库升级: https://github.com/yuweiguocn/GreenDaoUpgradeHelper

// 在project的build.gradle中配置:
allprojects {
	repositories {
		maven { url "https://jitpack.io" }
	}
}

// 在module的build.gradle中配置:
dependencies {
    implementation 'org.greenrobot:greendao:3.2.0'
    implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1'
}

// 混淆配置
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
    public static void dropTable(org.greenrobot.greendao.database.Database, boolean);
    public static void createTable(org.greenrobot.greendao.database.Database, boolean);
}


// 创建一个GreenDaoOpenHelper类 继承 DaoMaster.OpenHelper
public class MyGreenDaoOpenHelper extends DaoMaster.OpenHelper {

    public MyGreenDaoOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {

        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                DaoMaster.createAllTables(db, ifNotExists);
            }
            @Override
            public void onDropAllTables(Database db, boolean ifExists) {
                DaoMaster.dropAllTables(db, ifExists);
            }
            // 可传入多个xxxDao.class
        } , StudentDao.class);
    }
}

// 在创建DaoMaster的时候使用该GreenDaoOpenHelper类
/**
 * 判断数据库是否存在 不存在则创建
 * @return
 */
public DaoMaster getDaoMaster(){
    if(null == mDaoMaster){
    	mHelper = new MyGreenDaoOpenHelper(mContext, DB_NAME, null);
        mDaoMaster = new DaoMaster(mHelper.getWritableDatabase());
    }
    return mDaoMaster;
}

当数据库中的表或者字段更新时,将数据库的版本号加一,在打包覆盖安装之前的版本即可

数据库加密:https://github.com/sqlcipher/android-database-sqlcipher

// 在module的build.gradle中配置:
dependencies {
    implementation 'net.zetetic:android-database-sqlcipher:4.2.0'
}

// 在创建DaoMaster的时通过 mHelper.getEncryptedWritableDb() 对数据库进行加密
/**
 * 判断数据库是否存在 不存在则创建
 * @return
 */
public DaoMaster getDaoMaster(){
    if(null == mDaoMaster){
		mHelper = new MyGreenDaoOpenHelper(mContext, DB_NAME, null);
        mDaoMaster = new DaoMaster(mHelper.getEncryptedWritableDb(DeviceUtils.getUniqueDeviceId()));
    }
    return mDaoMaster;
}

增删改查功能测试

package com.zhr.test;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.zhr.test.auto.StudentDao;
import com.zhr.test.auto.TeacherDao;
import com.zhr.test.dao.DaoUtils;
import com.zhr.test.entity.CreditCard;
import com.zhr.test.entity.DetailInfo;
import com.zhr.test.entity.IdCard;
import com.zhr.test.entity.Student;
import com.zhr.test.entity.StudentAndTeacher;
import com.zhr.test.entity.Teacher;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Context mContext = MainActivity.this;
    private DaoUtils mDaoUtils;
    private int mOffset = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDaoUtils = new DaoUtils(mContext);
    }

    public void insert(View view){

        long idCardId = 1324;
        String name = "张三";
        Student student = new Student();
        student.setId(25L);
        student.setName(name);
        student.setAge(180);
        student.setAddress("上海");
        student.setIdCardId(idCardId);

        List<DetailInfo> detailInfos = new ArrayList<>();
        DetailInfo detailInfo = new DetailInfo();
        detailInfo.setComeFrom("杭州");
        detailInfo.setParentName("张三丰");
        detailInfos.add(detailInfo);
        student.setDetailInfos(detailInfos);

        IdCard idCard = new IdCard();
        idCard.setId(idCardId);
        idCard.setName(name);
        idCard.setOrganization("上海市公安局");

        List<CreditCard> creditCards = new ArrayList<>();
        CreditCard creditCard1 = new CreditCard();
        CreditCard creditCard2 = new CreditCard();
        creditCard1.setWhichBank("建行");
        creditCard1.setCreditCardId(student.getId());
        creditCard2.setWhichBank("工行");
        creditCard2.setCreditCardId(student.getId());
        creditCards.add(creditCard1);
        creditCards.add(creditCard2);

        boolean insert;
        if(null != mDaoUtils){
            insert = mDaoUtils.insert(student);
            insert = mDaoUtils.insert(idCard);
            insert = mDaoUtils.insertMult(creditCards);
        }else{
            insert = false;
        }
        Log.i(TAG , "插入一条数据至数据库成功?:" + insert);
    }

    public void insertMutl(View view){
        List<Student> students = new ArrayList<>();
        for(int i = 1; i < 11 ; i++){
            Student student = new Student();
            student.setId((long) i);
            student.setName("三李三" + i);
            student.setAge(18 + i);
            student.setAddress("上海");
            students.add(student);
        }

        List<Teacher> teachers = new ArrayList<>();
        for(int i = 1; i < 4 ; i++){
            Teacher teacher = new Teacher();
            teacher.setId((long) i);
            teacher.setName("王王王" + i);
            teacher.setAge(18 + i);
            teacher.setAddress("上海");
            teachers.add(teacher);
        }

        List<StudentAndTeacher> studentAndTeachers = new ArrayList<>();
        // 1号老师带34567号学生
        StudentAndTeacher sat1 = new StudentAndTeacher(null , 3L , 1L);
        StudentAndTeacher sat2 = new StudentAndTeacher(null , 4L , 1L);
        StudentAndTeacher sat3 = new StudentAndTeacher(null , 5L , 1L);
        StudentAndTeacher sat4 = new StudentAndTeacher(null , 6L , 1L);
        StudentAndTeacher sat5 = new StudentAndTeacher(null , 7L , 1L);
        // 2号老师带 45678号学生
        StudentAndTeacher sa1 = new StudentAndTeacher(null , 4L , 2L);
        StudentAndTeacher sa2 = new StudentAndTeacher(null , 5L , 2L);
        StudentAndTeacher sa3 = new StudentAndTeacher(null , 6L , 2L);
        StudentAndTeacher sa4 = new StudentAndTeacher(null , 7L , 2L);
        StudentAndTeacher sa5 = new StudentAndTeacher(null , 8L , 2L);
        // 3号老师带 56789号学生
        StudentAndTeacher s1 = new StudentAndTeacher(null , 5L , 3L);
        StudentAndTeacher s2 = new StudentAndTeacher(null , 6L , 3L);
        StudentAndTeacher s3 = new StudentAndTeacher(null , 7L , 3L);
        StudentAndTeacher s4 = new StudentAndTeacher(null , 8L , 3L);
        StudentAndTeacher s5 = new StudentAndTeacher(null , 9L , 3L);
        studentAndTeachers.add(sat1);
        studentAndTeachers.add(sat2);
        studentAndTeachers.add(sat3);
        studentAndTeachers.add(sat4);
        studentAndTeachers.add(sat5);
        studentAndTeachers.add(sa1);
        studentAndTeachers.add(sa2);
        studentAndTeachers.add(sa3);
        studentAndTeachers.add(sa4);
        studentAndTeachers.add(sa5);
        studentAndTeachers.add(s1);
        studentAndTeachers.add(s2);
        studentAndTeachers.add(s3);
        studentAndTeachers.add(s4);
        studentAndTeachers.add(s5);

        boolean insertMutl;
        if(null != mDaoUtils){
            insertMutl = mDaoUtils.insertMult(students);
            insertMutl = mDaoUtils.insertMult(teachers);
            insertMutl = mDaoUtils.insertMult(studentAndTeachers);
//            insertMutl = mDaoUtils.saveMult(students);
        }else{
            insertMutl = false;
        }
        Log.i(TAG, "插入多条数据至数据库成功?:" + insertMutl);
    }

    public void update(View view){
        Student student = new Student();
        // 根据主键去更新数据
        student.setId(7L);
        student.setName("李四1");
        student.setAge(100);
        student.setAddress("shanghai");
        boolean update;
        if(null != mDaoUtils){
            update = mDaoUtils.updateById(student);
        }else{
            update = false;
        }
        Log.i(TAG, "更新一条数据至数据库成功?:" + update);
    }

    public void delete(View view){
        Student student = new Student();
        student.setId(1L);
        boolean delete;
        if(null != mDaoUtils){
            delete = mDaoUtils.deleteById(student);
        }else{
            delete = false;
        }
        Log.i(TAG, "删除一条数据至数据库成功?:" + delete);
    }

    public void deleteAll(View view){
        boolean deleteAll;
        if(null != mDaoUtils){
            deleteAll = mDaoUtils.deleteAll(Student.class);
        }else {
            deleteAll = false;
        }
        Log.i(TAG, "删除所有数据至数据库成功?:" + deleteAll);
    }

    public void quary(View view){
        boolean quary;
        Student student;
        if(null != mDaoUtils){
            try {
                student = (Student) mDaoUtils.quaryById(Student.class , 2L);
                Log.i(TAG, "id:" + student.getId() + ",name:" + student.getName()
                        + ",age:" + student.getAge() + ",address:" + student.getAddress()
                        + ",info:" + student.getDetailInfos());
                quary = true;
            } catch (Exception e) {
                e.printStackTrace();
                quary = false;
            }
        }else {
            quary = false;
        }
        Log.i(TAG, "从数据库中查找一条数据成功?:" + quary);
    }

    public void quaryAll(View view){
        boolean quaryAll;
        if(null != mDaoUtils){
            try {
                List<Student> students = (List<Student>) mDaoUtils.quaryAll(Student.class);
                for(Student student : students){
                    Log.i(TAG, "id:" + student.getId() + ",name:" + student.getName()
                        + ",age:" + student.getAge() + ",address:" + student.getAddress());
                }
                quaryAll = true;
            } catch (Exception e) {
                e.printStackTrace();
                quaryAll = false;
            }
        }else {
            quaryAll = false;
        }
        Log.i(TAG, "从数据库中查找所有数据成功?:" + quaryAll);
    }

    /**
     * 使用复合条件查询语句进行查询操作
     * @param view
     */
    public void quaryBuilder(View view){
        boolean quaryBuilder;
        if(null != mDaoUtils){
            try {
                // SQL原生语句查询
//                List<Student> students = mDaoUtils.nativeQuary(Student.class);
                // GreenDao 多种条件查询
//                List<Student> students = (List<Student>) mDaoUtils.quaryList(Student.class).where(StudentDao.Properties.Age.eq(18) , StudentDao.Properties.Address.eq("上海")).list();
                // 年龄降序排列
//                List<Student> students = (List<Student>) mDaoUtils.quaryList(Student.class).where(StudentDao.Properties.Name.like("%李%")).orderDesc(StudentDao.Properties.Age).list();
                // 使用迭代器遍历集合数据
//                Iterator<Student> iterator = (Iterator<Student>) mDaoUtils.quaryList(Student.class).orderDesc(StudentDao.Properties.Age).listIterator();
//                while (iterator.hasNext()){
//                    Student next = iterator.next();
//                    Log.i(TAG, "Student: " + next);
//                }

                // 分页加载数据
//                int limit = 2;
//                LazyList<Student> students = (LazyList<Student>)mDaoUtils.quaryList(Student.class).offset(mOffset * limit).limit(limit).listLazy();
//                mOffset++;
//                // lazyList 使用完要关闭
//                students.close();

                // 查询完了之后删除查询出来的数据
//                QueryBuilder<Student> where = (QueryBuilder<Student>) mDaoUtils.quaryList(Student.class).where(StudentDao.Properties.Age.eq(18), StudentDao.Properties.Address.eq("上海"));
//                where.buildDelete().executeDeleteWithoutDetachingEntities();

//                for(Student student : students){
//                    Log.i(TAG, "id:" + student.getId() + ",name:" + student.getName()
//                      + ",age:" + student.getAge() + ",address:" + student.getAddress()
//                            + ",organization: " + student.getIdCard().getOrganization());
//                }

                // 查询上海大于100岁的身份证属于哪个派出所  一对一  一对多   关联查询
//                List<Student> students = (List<Student>) mDaoUtils.quaryList(Student.class).where(StudentDao.Properties.Age.gt(100) , StudentDao.Properties.Address.eq("上海")).list();
//                for(Student student : students){
//                    Log.i(TAG, "name: " + student.getName() + ",organization: " + student.getIdCard().getOrganization() + ",creditCard: " + student.getCreditCards());
//                }

//                List<Student> students = (List<Student>) mDaoUtils.quaryList(Student.class).where(StudentDao.Properties.Id.eq(5)).list();
//                for(Student student : students){
//                    Log.i(TAG, "teachers: " + student.getTeachers());
//                }
//                List<Teacher> teachers = (List<Teacher>) mDaoUtils.quaryList(Teacher.class).where(TeacherDao.Properties.Id.eq(1)).list();
//                for(Teacher teacher : teachers){
//                    Log.i(TAG, "students: " + teacher.getStudents());
//                }

                // 多线程查询
                new Thread(){
                    @Override
                    public void run() {
                        List<Student> list = (List<Student>) mDaoUtils.quaryList(Student.class).build().forCurrentThread().list();
                        Log.i(TAG, "list " + list);
                    }
                }.start();

                quaryBuilder = true;
            } catch (Exception e) {
                e.printStackTrace();
                quaryBuilder = false;
            }
        }else {
            quaryBuilder = false;
        }
        Log.i(TAG, "原生查询条件查询多条数据成功?:" + quaryBuilder);
    }
}

一对一查询

一般来说,一个学生对应一个身份证,新建一个IdCard 实体类。
在Student实体类中,声明一个idCardId。使用注解@ToOne()将idCardId和IdCard实体类中的id进行关联

@Entity
public class Student {

    /**
     * 主键自增类型要设置为Long
     */
    @Id(autoincrement = true)
    private Long id;
    private String name;
    private String address;
    private int age;
    private Long idCardId;

    /**
     * ToOne
     * idCardId 作为外键和idCard的id进行关联
     * 需在本Bean中声明一个idCardId字段
     * 可以和idCard的id字段名不同
     */
    @ToOne(joinProperty = "idCardId")
    private IdCard idCard;    
}

@Entity
public class IdCard {

    @Id(autoincrement = true)
    private Long id;
    private String name;
    private String organization  
}

// 查询时使用 获取学生关联的身份证的信息,关联的字段为身份证id
student.getIdCard().getOrganization();

一对多查询

一般来说,一个学生对应多个信用卡,新建一个CreditCard实体类。
在Student实体类中。使用注解@ToMany()将creditCardId和CreditCard实体类中的id进行关联,CreditCard实体类中需要声明creditCardId字段

@Entity
public class Student {

    /**
     * 主键自增类型要设置为Long
     */
    @Id(autoincrement = true)
    private Long id;
    @NotNull
    private String name;
    @NotNull
    private String address;
    @NotNull
    private int age;
    private Long idCardId;

    /**
     * ToOne
     * idCardId 作为外键和idCard的id进行关联
     * 需在本Bean中声明一个idCardId字段
     * 可以和idCard的id字段名不同
     */
    @ToOne(joinProperty = "idCardId")
    private IdCard idCard;

    /**
     * ToMany
     * creditCardId 作为外键和student的id进行关联
     * 不需在本Bean中声明一个creditCardId字段
     * 需要在creditCard中声明一个creditCardId字段
     * 每一个creditCardI的对应的是此student的id
     */
    @ToMany(referencedJoinProperty  = "creditCardId")
    private List<CreditCard> creditCards;
}

----------------------------------------------------------------------------------------
// CreditCard

@Entity
public class CreditCard {

    @Id(autoincrement = true)
    private Long id;
    @NotNull
    private Long creditCardId;
    @NotNull
    private String whichBank;
}

// 查询时使用 获取学生关联的多个信用卡的信息,关联的字段为信用卡id
students.get(i).getCreditCards().getCreditCardId();

多对多查询

一般来说,多个学生对应多个老师,新建一个Teacher实体类,并且新建一个学生和老师对应关系的StudentAndTeachcer实体类
在Student实体类中使用注解@ToMany()和 @JoinEntity()将studentId在StudentAndTeachcer类中和teacherId进行关联;在Teacher实体类中使用注解@ToMany()和 @JoinEntity()将teacherId在StudentAndTeachcer类中和studentId进行关联

@Entity
public class Student {

    /**
     * 主键自增类型要设置为Long
     */
    @Id(autoincrement = true)
    private Long id;
    @NotNull
    private String name;
    @NotNull
    private String address;
    @NotNull
    private int age;
    private Long idCardId;

    /**
     * ToOne
     * idCardId 作为外键和idCard的id进行关联
     * 需在本Bean中声明一个idCardId字段
     * 可以和idCard的id字段名不同
     */
    @ToOne(joinProperty = "idCardId")
    private IdCard idCard;

    /**
     * ToMany
     * creditCardId 作为外键和student的id进行关联
     * 不需在本Bean中声明一个creditCardId字段
     * 需要在creditCard中声明一个creditCardId字段
     * 每一个creditCardI的对应的是此student的id
     */
    @ToMany(referencedJoinProperty  = "creditCardId")
    private List<CreditCard> creditCards;

    @ToMany
    @JoinEntity(entity = StudentAndTeacher.class , sourceProperty = "studentId"
        , targetProperty = "teacherId")
    private List<Teacher> teachers;
}

-----------------------------------------------------------------------------------------------------------------------------------------------
// Teacher

@Entity
public class Teacher {

    /**
     * 主键自增类型要设置为Long
     */
    @Id(autoincrement = true)
    private Long id;
    @NotNull
    private String name;
    @NotNull
    private String address;
    @NotNull
    private int age;

    @ToMany
    @JoinEntity(entity = StudentAndTeacher.class , sourceProperty = "teacherId"
            , targetProperty = "studentId")
    List<Student> students;
}

-----------------------------------------------------------------------------------------------------------------------------------------------
// Teacher
@Entity
public class StudentAndTeacher {

    @Id(autoincrement = true)
    Long id;
    Long studentId;
    Long teacherId;
}

缓存字段为集合类型的数据

学生中有一个详细信息的字段,此字段为集合类型数据,将此数据以字符串的类型存储至数据库

@Entity
public class Student {

    /**
     * 主键自增类型要设置为Long
     */
    @Id(autoincrement = true)
    private Long id;
    private String name;
    private String address;
    private int age;
    private Long idCardId;
    
    /**
     * 如果不需要对其中的字段进行单独查询,只是做存储展示时
     * 可以使用这种方法将集合转为字符串存储
     */
    @Convert(converter = ListConvert.class, columnType = String.class)
    private List<DetailInfo> detailInfos;
}

---------------------------------------------------------------------------------------------

// ListConvert

package com.zhr.test;

import com.alibaba.fastjson.JSON;
import com.zhr.test.entity.DetailInfo;
import org.greenrobot.greendao.converter.PropertyConverter;
import java.util.List;

/**
 * 参数转换类 将xxx类型转换为xxx类型存储在数据库
 */
public class ListConvert implements PropertyConverter<List<DetailInfo>, String> {

    /**
     * 字符串转集合
     * @param databaseValue
     * @return
     */
    @Override
    public List<DetailInfo> convertToEntityProperty(String databaseValue) {
        return JSON.parseArray(databaseValue , DetailInfo.class);
    }

    /**
     * 集合转字符串
     * @param entityProperty
     * @return
     */
    @Override
    public String convertToDatabaseValue(List<DetailInfo> entityProperty) {
        return JSON.toJSONString(entityProperty);
    }
}

代码下载请移步:https://download.csdn.net/download/zxc514257857/11977445

你可能感兴趣的:(【Android第三方库使用】)