GreenDao一对多关系操作

 

概述

        GreenDAO是一个对象关系映射(ORM)的框架,能够提供一个接口通过操作对象的方式去操作关系型数据库,它能够让你操作数据库时更简单、更方便。


前言

        关于GreenDao基本使用教程,大家可以参照我的另一篇文章最短时间学会使用GreenDao3.2(方便小白快速上手)

        关于数据库之间的关联关系,大家可以参照网上的一篇博文
GreenDao教程(3):一对一,一对多,多对多

         针对数据库多表之间的关联关系,“一对多”使用的较为频繁,而“一对一”和“多对多”使用较少,因此本文旨在通过示例来带领大家更快的理解和使用greendao来处理“一对多”的关系。
 

GreenDao添加依赖

为了减少大家的学习成本,此处把GreenDao的使用再赘述一遍。

Step 1:

GreenDao一对多关系操作_第1张图片

Step 2:

GreenDao一对多关系操作_第2张图片

当然你也可以通过Project Structure来添加greendao的依赖。
如下图:
GreenDao一对多关系操作_第3张图片
好了,下面就可以使用GreenDao了。
 

GreenDao(一对多关系)使用示例详解

先看一下项目结构,如下图:
GreenDao一对多关系操作_第4张图片

示例描述:
简明扼要,每个父亲(ParentBean)可能有多个孩子,但是每个孩子(ChildrenBean)只有一个父亲。就以此为例。

Num 1. Bean文件

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操作数据库的时候用到,如下图:
GreenDao一对多关系操作_第5张图片

Num 2. 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"
    ........>

 

Num 3. 封装的用于GreenDao增删改查的工具类
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;
   }


}

Num 4. 主程序和布局文件

(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>

如图:
GreenDao一对多关系操作_第6张图片

(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;
        }
    }
}

好了至此完结。

好了,示例代码使用演示完成。
 

Greendao操作结果

        程序运行之后,即将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

如果你能查询到下图的界面,说明准备工作已经完成了。
如图:
GreenDao一对多关系操作_第7张图片

好了,下面教大家如何在终端中导出xxxx.db数据库。

step 1:通过adb shell找到xxx.db(demo中的数据库名字是乱起的)的存在路径,如下图
在这里插入图片描述

step 2:将xxx.db导出到桌面
在这里插入图片描述

step 3:通过ubuntu的一款数据库管理软件DB Browser for SQLite来进行查看。(安装很简单,不再赘述).

数据库查看结果如下
parent:
GreenDao一对多关系操作_第8张图片

children:
GreenDao一对多关系操作_第9张图片

补充

关于数据库管理软件DB Browser for SQLite,略微做点补充。DB Browser for SQLite不仅可以查看数据库还可以编辑。
当你对某个字段进行编辑的时候可能会报错,如图
GreenDao一对多关系操作_第10张图片

这是典型的数据库读写权限不够造成的。直接赋予权限即可。执行如下命令:
在这里插入图片描述

注意是

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

你可能感兴趣的:(数据库)