文章参考自:老罗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/
// 在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
}
-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.**
// 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