GreenDAO是一个对象关系映射(ORM)的框架,能够提供一个接口通过操作对象的方式去操作关系型数据库,它能够让你操作数据库时更简单、更方便。
关于GreenDao基本使用教程,大家可以参照我的另一篇文章最短时间学会使用GreenDao3.2(方便小白快速上手)
关于数据库之间的关联关系,大家可以参照网上的一篇博文
GreenDao教程(3):一对一,一对多,多对多
针对数据库多表之间的关联关系,“一对多”使用的较为频繁,而“一对一”和“多对多”使用较少,因此本文旨在通过示例来带领大家更快的理解和使用greendao来处理“一对多”的关系。
为了减少大家的学习成本,此处把GreenDao的使用再赘述一遍。
当然你也可以通过Project Structure来添加greendao的依赖。
如下图:
好了,下面就可以使用GreenDao了。
示例描述:
简明扼要,每个父亲(ParentBean)可能有多个孩子,但是每个孩子(ChildrenBean)只有一个父亲。就以此为例。
ParentBean具有的属性:
@Entity
public class ParentBean {
private static final String TAG = "ParentBean";
/**
* Id主键自增
*/
@Id(autoincrement = true)
private Long id;
/**
* 年龄
*/
@NotNull
private String name;
/**
* 拥有的孩子数量
*/
@NotNull
private int childCount;
/**
* 每个父亲对应的孩子列表
*/
@ToMany(referencedJoinProperty = "parentId")
private List<ChildrenBean> childrenBeanList;
}
ChildrenBean具有的属性:
@Entity
public class ChildrenBean {
/**
* 主键自增
*/
@Id
private Long id;
/**
* 姓名
*/
@NotNull
private String name;
/**
* 性别
*/
@NotNull
private String sex;
/**
* 年龄
*/
@NotNull
private int age;
/**
* parentId::用于标记孩子归属哪一个父亲
*/
@NotNull
private Long parentId;
}
其中重点关注
ParentBean.java中的
/**
* 每个父亲对应的孩子列表
*/
@ToMany(referencedJoinProperty = "parentId")
private List<ChildrenBean> childrenBeanList;
以及 ChildrenBean.java中
/**
* parentId::用于标记孩子归属哪一个父亲
*/
@NotNull
private Long parentId;
上述两个字段是实现”一对多“的关键。
然后执行Build---->Make Project操作。之后,ParentBean.java中和Children.java中会自动生成一些set和get方法以及构造函数扥等。
下面贴出自动生成后的完整的文件。
ParentBean.java
package com.example.zq.gdonetomanydemo.bean;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.DaoException;
import greendao.DaoSession;
import greendao.ChildrenBeanDao;
import greendao.ParentBeanDao;
@Entity
public class ParentBean {
private static final String TAG = "ParentBean";
/**
* Id主键自增
*/
@Id(autoincrement = true)
private Long id;
/**
* 年龄
*/
@NotNull
private String name;
/**
* 拥有的孩子数量
*/
@NotNull
private int childCount;
/**
* 每个父亲对应的孩子列表
*/
@ToMany(referencedJoinProperty = "parentId")
private List<ChildrenBean> childrenBeanList;
//*****************************************自动注入代码部分 开始*********************************
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 907959384)
private transient ParentBeanDao myDao;
@Generated(hash = 1508028638)
public ParentBean(Long id, @NotNull String name, int childCount) {
this.id = id;
this.name = name;
this.childCount = childCount;
}
@Generated(hash = 38677353)
public ParentBean() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getChildCount() {
return this.childCount;
}
public void setChildCount(int childCount) {
this.childCount = childCount;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1363380196)
public List<ChildrenBean> getChildrenBeanList() {
if (childrenBeanList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
ChildrenBeanDao targetDao = daoSession.getChildrenBeanDao();
List<ChildrenBean> childrenBeanListNew = targetDao
._queryParentBean_ChildrenBeanList(id);
synchronized (this) {
if (childrenBeanList == null) {
childrenBeanList = childrenBeanListNew;
}
}
}
return childrenBeanList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 2107861997)
public synchronized void resetChildrenBeanList() {
childrenBeanList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/**
* called by internal mechanisms, do not call yourself.
*/
@Generated(hash = 1966188193)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getParentBeanDao() : null;
}
//******************************************自动注入代码部分 结束**********************************
@Override
public String toString() {
return "ParentBean{" +
"id=" + id +
", name='" + name + '\'' +
", childCount=" + childCount +
", childrenBeanList=" + childrenBeanList +
", daoSession=" + daoSession +
", myDao=" + myDao +
'}';
}
}
ChildrenBean.java
package com.example.zq.gdonetomanydemo.bean;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.Generated;
@Entity
public class ChildrenBean {
/**
* 主键自增
*/
@Id
private Long id;
/**
* 姓名
*/
@NotNull
private String name;
/**
* 性别
*/
@NotNull
private String sex;
/**
* 年龄
*/
@NotNull
private int age;
/**
* parentId::用于标记孩子归属哪一个父亲
*/
@NotNull
private Long parentId;
//*****************************************自动注入代码部分 开始*********************************
@Generated(hash = 1298246657)
public ChildrenBean(Long id, @NotNull String name, @NotNull String sex, int age,
@NotNull Long parentId) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.parentId = parentId;
}
@Generated(hash = 1056885546)
public ChildrenBean() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return this.sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public Long getParentId() {
return this.parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
//*****************************************自动注入代码部分 结束*********************************
@Override
public String toString() {
return "ChildrenBean{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", parentId=" + parentId +
'}';
}
}
同时还生成了几个文件,这个几个类会在使用GreenDao操作数据库的时候用到,如下图:
package com.example.zq.gdonetomanydemo;
import android.app.Application;
import android.database.sqlite.SQLiteDatabase;
import greendao.DaoMaster;
import greendao.DaoSession;
public class MyApplication extends Application {
private static MyApplication application;
private SQLiteDatabase db;
private DaoSession mDaoSession;
@Override
public void onCreate() {
super.onCreate();
application = this;
setDatabase();
}
public static MyApplication getApplication() {
return application;
}
/**
* 进行greenDao的初始化
*/
private void setDatabase() {
DaoMaster.DevOpenHelper mHelper = new DaoMaster.DevOpenHelper(this, "robot_interaction.db", null);
db = mHelper.getWritableDatabase();
DaoMaster mDaoMaster = new DaoMaster(db);
mDaoSession = mDaoMaster.newSession();
}
public DaoSession getDaoSession() {
return mDaoSession;
}
public SQLiteDatabase getDb() {
return db;
}
}
不要忘了在manifest.xml中文件中引入
<application
........
android:name=".MyApplication"
........>
package com.example.zq.gdonetomanydemo;
import android.util.Log;
import com.example.zq.gdonetomanydemo.bean.ChildrenBean;
import com.example.zq.gdonetomanydemo.bean.ParentBean;
import java.util.List;
import greendao.ChildrenBeanDao;
import greendao.ParentBeanDao;
public class GreenDaoManager {
private static final String TAG = "GreenDaoManager";
private static GreenDaoManager instance;
private final ParentBeanDao parentBeanDao;
private final ChildrenBeanDao childrenBeanDao;
public static GreenDaoManager getInstance() {
if (instance == null) {
synchronized (GreenDaoManager.class) {
if (instance == null) {
instance = new GreenDaoManager();
}
}
}
return instance;
}
private GreenDaoManager() {
parentBeanDao = MyApplication.getApplication().getDaoSession().getParentBeanDao();
childrenBeanDao = MyApplication.getApplication().getDaoSession().getChildrenBeanDao();
}
//*************************************parentBean的增删改查****************************************
/**
* 插入parent数据
*
* @param bean
* @return
*/
long insertParentData(ParentBean bean) {
Log.d(TAG, "insert parent===>" + bean);
return parentBeanDao.insert(bean);
}
/**
* 删除parent数据
*
* @param id
*/
public void deleteParentData(Long id) {
Log.d(TAG, "delete parent===>id" + id);
parentBeanDao.deleteByKey(id);
}
/**
* 更新parent数据
*
* @param bean
*/
public void updateParentData(ParentBean bean) {
Log.d(TAG, "update parent===>" + bean);
parentBeanDao.update(bean);
}
/**
* 查询所有的parent数据
*
* @return
*/
public List<ParentBean> queryAllParentData() {
//两种方式获取是一样的,查看源码便知
List<ParentBean> list = parentBeanDao.queryBuilder().list();
List<ParentBean> list1 = parentBeanDao.loadAll();
Log.i(TAG, "queryAllParentData: list::" + list + " list1::" + list1);
return list;
}
/**
* 查询所有parent下对应的children
*/
public void queryAllChildrenForParent() {
List<ParentBean> list = parentBeanDao.queryBuilder().list();
//todo 经过了遍历之后才能取得列表数据
for (ParentBean bean : list) {
List<ChildrenBean> childrenBeanList = bean.getChildrenBeanList();
Log.i(TAG, "queryChildrenForParentId: childrenBeanList:::" + childrenBeanList);
}
}
//*************************************childBean的增删改查****************************************
/**
* 插入children数据
*
* @param bean
* @return
*/
long insertChildrenData(ChildrenBean bean) {
Log.d(TAG, "insert children===>" + bean);
return childrenBeanDao.insert(bean);
}
/**
* 删除children数据
*
* @param id
*/
public void deleteChildrenData(Long id) {
Log.d(TAG, "delete children===>id" + id);
childrenBeanDao.deleteByKey(id);
}
/**
* 更新children数据
*
* @param bean
*/
public void updateChildrenData(ChildrenBean bean) {
Log.d(TAG, "update children===>" + bean);
childrenBeanDao.update(bean);
}
/**
* 查询所有的children数据
*
* @return
*/
public List<ChildrenBean> queryAllChildrenData() {
//两种方式获取是一样的,查看源码便知
List<ChildrenBean> list = childrenBeanDao.queryBuilder().list();
List<ChildrenBean> list1 = childrenBeanDao.loadAll();
Log.i(TAG, "queryAllChildrenData: list::" + list + " list1::" + list1);
return list;
}
/**
* 查询某个parentId下对应的children
*
* @param parentId
* @return
*/
public List<ChildrenBean> queryChildrenDataAccordField(Long parentId) {
List<ChildrenBean> list = childrenBeanDao.queryBuilder().where(ChildrenBeanDao.Properties.ParentId.eq(parentId)).list();
Log.i(TAG, "queryChildrenDataAccordField: list::" + list);
return list;
}
}
(1).布局文件activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/query_all_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询所有的父亲" />
<Button
android:id="@+id/query_all_children"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询所有的孩子" />
<Button
android:id="@+id/query_children_for_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询某一父亲对应的孩子" />
LinearLayout>
(2).MainActivity.java
package com.example.zq.gdonetomanydemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.example.zq.gdonetomanydemo.bean.ChildrenBean;
import com.example.zq.gdonetomanydemo.bean.ParentBean;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private GreenDaoManager mGreenDaoManager;
private Button mAllParentQuery;
private Button mAllChildrenQuery;
private Button mChildrenForParentQuery;
/**
* 用于后续获取父亲“王二”对应的所有孩子
*/
private long wangerId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initView() {
mAllParentQuery = (Button) findViewById(R.id.query_all_parent);
mAllChildrenQuery = (Button) findViewById(R.id.query_all_children);
mChildrenForParentQuery = (Button) findViewById(R.id.query_children_for_parent);
mAllParentQuery.setOnClickListener(this);
mAllChildrenQuery.setOnClickListener(this);
mChildrenForParentQuery.setOnClickListener(this);
}
private void initData() {
//张三
mGreenDaoManager = GreenDaoManager.getInstance();
ParentBean parentBean1 = new ParentBean(null, "张三", 1);
mGreenDaoManager.insertParentData(parentBean1);
ChildrenBean childrenBean = new ChildrenBean(null, "张三的儿子", "male", 12, parentBean1.getId());
mGreenDaoManager.insertChildrenData(childrenBean);
//李四
ParentBean parentBean2 = new ParentBean(null, "李四", 2);
mGreenDaoManager.insertParentData(parentBean2);
ChildrenBean childrenBean2 = new ChildrenBean(null, "李四的儿子", "male", 21, parentBean2.getId());
ChildrenBean childrenBean3 = new ChildrenBean(null, "李四的女儿", "female", 22, parentBean2.getId());
mGreenDaoManager.insertChildrenData(childrenBean2);
mGreenDaoManager.insertChildrenData(childrenBean3);
//王二
ParentBean parentBean3 = new ParentBean(null, "王二", 3);
wangerId = mGreenDaoManager.insertParentData(parentBean3);
ChildrenBean childrenBean4 = new ChildrenBean(null, "王二的儿子", "male", 12, parentBean3.getId());
ChildrenBean childrenBean5 = new ChildrenBean(null, "王二的大女儿", "female", 22, parentBean3.getId());
ChildrenBean childrenBean6 = new ChildrenBean(null, "王二的小女儿", "female", 15, parentBean3.getId());
mGreenDaoManager.insertChildrenData(childrenBean4);
mGreenDaoManager.insertChildrenData(childrenBean5);
mGreenDaoManager.insertChildrenData(childrenBean6);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.query_all_parent:
// TODO 18/09/24
mGreenDaoManager.queryAllParentData();
break;
case R.id.query_all_children:
// TODO 18/09/24
mGreenDaoManager.queryAllChildrenData();
break;
case R.id.query_children_for_parent:
// TODO 18/09/24
//查询王二对应的所有孩子
mGreenDaoManager.queryChildrenDataAccordField(wangerId);
break;
default:
break;
}
}
}
好了至此完结。
好了,示例代码使用演示完成。
程序运行之后,即将parent和children数据初始化完毕。因此我们可以将packname/data/data/databases/中的xx.db数据库导出来,通过相应的数据库查看软件进行查看。
将数据库库导出,需要满足以下几个条件:
(1).考虑到数据库的导出需要root权限,而一般的手机默认是没有root权限的,因此我们可以使用AVD模拟器。
(2).随着android studio升级到3.0+,我们在android studio2.3中使用的Andriod Device Monitor将不存在(被废弃了)。至于打开Device project Explorer的方式可参照AndriodStudio 3.1查看data数据
(3).如果你已经运行了AVD模拟器,但是打开Device project Explorer,却什么也没有,请将你的AVD的镜像版本>=21,参照博客Android开发之——Advanced profiling is unavable for the selected process
好了,下面教大家如何在终端中导出xxxx.db数据库。
step 1:通过adb shell找到xxx.db(demo中的数据库名字是乱起的)的存在路径,如下图
step 3:通过ubuntu的一款数据库管理软件DB Browser for SQLite来进行查看。(安装很简单,不再赘述).
关于数据库管理软件DB Browser for SQLite,略微做点补充。DB Browser for SQLite不仅可以查看数据库还可以编辑。
当你对某个字段进行编辑的时候可能会报错,如图
这是典型的数据库读写权限不够造成的。直接赋予权限即可。执行如下命令:
注意是
sudo chomd 777 xxx.db
而不是
sudo chomd a+x xxx.db
sudo chomd a+x xxx.db授予的是可执行权限,而不包括读写权限。
好了,关于greendao一对多的操作至此完结。小伙伴如果有任何疑问可留言,大家相互交流。
下面附上示例demo
https://download.csdn.net/download/zhangqunshuai/10684488