Android中关系型数据库 GreenDao 3.2.2的使用
文章参考自:老罗GreenDao数据库课程以及 Nate - Android框架-GreenDao
前言
-
android中的数据存储:
网络存储
数据库存储
SharedPreference 存储
ContentProvider存储
文件存储 -
GreenDao简介:
是一款优秀的ORM框架(Object Relational Mapping)
对象关系映射,其思想将关系数据库中表的数据映射成为对象。程序员就可以将对数据库的操作转化为对对象的操作。其目的是让程序员以面向对象的思想来实现对数据库的操作。
是对SQlite数据库的封装 -
优秀的ORM框架还有
OrmLite 、 SugarOrm 、 LitePal 、 GreenDao -
关系型数据库Sql和非关系型数据库NoSql
关系型数据库最典型的数据结构是表,是由二维表及其之间的联系说组成的一个数据组织,代表数据库是MySql、Oracle
非关系型数据库严格上不是一种数据库,是一种数据结构化存储方法的集合,可以是文档或者是键值对等,代表数据库是MongoDB、Redis -
Android原生Api操作数据库有什么不便
要手动拼装SQL
要自己写操作数据库的常规代码
不能自动把数据库中的数据映射
没有实现级联查询 -
为什么要选择GreenDao
性能、文档、流行性、上手方便、拓展性 -
GreenDao资料查询地址
GreenDao的Github地址: https://github.com/greenrobot/greenDAO
GreenDao官网: http://greenrobot.org/greendao/
GreenDao Api地址: http://greenrobot.org/files/greendao/javadoc/current/
使用
- 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}
- 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.**
- 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数据库的升级及加密
// DaoManagerpackage 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; } }}---------------------------------------------------------------------------------------------// DaoUtilspackage 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.OpenHelperpublic 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进行关联
@Entitypublic 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; }@Entitypublic class IdCard { @Id(autoincrement = true) private Long id; private String name; private String organization }// 查询时使用 获取学生关联的身份证的信息,关联的字段为身份证idstudent.getIdCard().getOrganization();
一对多查询
一般来说,一个学生对应多个信用卡,新建一个CreditCard实体类。
在Student实体类中。使用注解@ToMany()将creditCardId和CreditCard实体类中的id进行关联,CreditCard实体类中需要声明creditCardId字段
@Entitypublic 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@Entitypublic class CreditCard { @Id(autoincrement = true) private Long id; @NotNull private Long creditCardId; @NotNull private String whichBank;}// 查询时使用 获取学生关联的多个信用卡的信息,关联的字段为信用卡idstudents.get(i).getCreditCards().getCreditCardId();
多对多查询
一般来说,多个学生对应多个老师,新建一个Teacher实体类,并且新建一个学生和老师对应关系的StudentAndTeachcer实体类
在Student实体类中使用注解@ToMany()和 @JoinEntity()将studentId在StudentAndTeachcer类中和teacherId进行关联;在Teacher实体类中使用注解@ToMany()和 @JoinEntity()将teacherId在StudentAndTeachcer类中和studentId进行关联
@Entitypublic 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@Entitypublic 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@Entitypublic class StudentAndTeacher { @Id(autoincrement = true) Long id; Long studentId; Long teacherId;}
缓存字段为集合类型的数据
学生中有一个详细信息的字段,此字段为集合类型数据,将此数据以字符串的类型存储至数据库
@Entitypublic 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;}---------------------------------------------------------------------------------------------// ListConvertpackage 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
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- 一句话锁定MySQL数据占用元凶
- ContentProvider使用详解
- android viewmodel 数据刷新异常
- Android中Adapter使用ViewHolder优化
- Android学习系列(19)-App数据格式之解析Xml
- Android(安卓)GreenDao3.2.2简单使用
- [原]Android上GTalk以及Push机制的XMPP数据选择使用protobuf格式
- ContentProvider介绍