GreenDao 一对多ToMany使用多表关联查询

最近在做项目的时候遇到了一对多的结构数据存储问题。由于前面的是使用的greendao框架,所以就研究了一下这方面的资料。但是网上的都是官网的一些资料。下面我就简单的介绍一下如何使用。由于是demo很简单所以也不放具体的项目了。

第一步建立第一个学生的类为Student。说明一下,这里必须要有主键,如果不是自增长的,那么在创建对象的时候,就需要赋值。  重点说明一下这个TId,这记录那个外键对应的单一的Teacher类的主键的,一定要有,不然找不到对应的关系。同时这里最好加上下面的那个Teacher对象,当然某些场景是可以使用的(非必须)。

@Entity
public class Student {

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

    @ToOne(joinProperty = "tId")
    private Teacher teacher;
}

接下来就是建立对应的Teacher类。这里需要采用ToMany注解,这里的外键就是上面学生类定义的TID。至于为什么要定义成Long,这个理由和主键定义成Long一样的道理。原因是主键自增类型必须是Long(注意是大写的L)

@Entity
public class Teacher {


    @Id(autoincrement = true)
    private Long id;
    private String name;
    @ToMany(referencedJoinProperty = "tId")
    private List<Student> studnets; // not persisted
}

这里需要注意的是,teacher类自动生成提供的getstudents的方法,如果在某些场景下直接使用是会报错的并也没有提供对应的set方法,所以这里最好重新get、set方法。同样的这里存在后面的需要去重复的问题,所以重写相关的equals、hascode方法。

   public void addStudent(Student student){
        if (studnets == null){
            studnets = new ArrayList<>();
        }
        studnets.add(student);
    }

    public List<Student> getStudens(){
        return studnets;
    } 

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Teacher brandInfo = (Teacher) o;

        if (!name.equals(brandInfo.name)) return false;
        return name.equals(brandInfo.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }

准备工作到这里就做完了。接下来就是数据处理的部分了。模拟了每个老师有两个学生。这里用两个list集合分别存储对应的学生和老师。需要注意的是,这里的学生的类的TId必须要是老师存储成功的id.所以这里在存储的时候要获取单个的存储ID老师就只能采用了单个插入,而学生则可以最后一期存储。

  DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "mydb.db", null);
        DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
        DaoSession daoSession = daoMaster.newSession();
        List<Teacher> mutableList = new ArrayList<>();
        List<Student> studentList = new ArrayList<>();

        daoSession.getTeacherDao().deleteAll();
        daoSession.getStudentDao().deleteAll();
        daoSession.startAsyncSession();
        Log.d(TAG, "onCreate: 0");
        for (int i = 0;i<10000;i++) {
            Teacher teacher = new Teacher();
            teacher.setName("zhong"+i);
            Long sid =daoSession.getTeacherDao().insertOrReplace(teacher);
            for (int j = 0;j<2;j++) {
                Student student = new Student();
                student.setName( i+ "gua");
                teacher.addStudent(student);
                student.setTId(sid);
                student.setTeacher(teacher);
                studentList.add(student);
            }
            mutableList.add(teacher);
        }
        daoSession.getStudentDao().insertInTx(studentList);

接下来先看官网的三个例子吧,分别是多表联合、两表联合和自关联查询。

  以下是官方实例:涉及三个实例City, Country, and Continent.查询欧洲的所有人数超过一百万的所有城市:
    QueryBuilder qb = cityDao.queryBuilder().where(Properties.Population.ge(1000000));
    Join country = qb.join(Properties.CountryId, Country.class);
    Join continent = qb.join(country, CountryDao.Properties.ContinentId, Continent.class, ContinentDao.Properties.Id);
    continent.where(ContinentDao.Properties.Name.eq("Europe"));
    List<City> bigEuropeanCities = qb.list();

    QueryBuilder<User> queryBuilder = userDao.queryBuilder();
    queryBuilder.join(Address.class, AddressDao.Properties.userId)
    .where(AddressDao.Properties.Street.eq("Sesame Street"));
    List<User> users = queryBuilder.list();

    QueryBuilder qb = userDao.queryBuilder();
    qb.where(Properties.FirstName.eq("Joe"),
    qb.or(Properties.YearOfBirth.gt(1970),
    qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));

由于项目的需求是模糊查询,我这里也采用模糊需求来查询,根据上面的数据查询学生中的名字含有1的所有老师。当然这个实现之后,后面的各种并、或、相等、排序等都是修改某些地方就可以实现,这里就不详细介绍。

第一种实现方式参考官方的例子,两表联合查询。先生成QueryBuilder对象,然后使用关键字join,关联对应表对象和相关的外键。至于join有三种使用方式,详细的介绍可以参考官网,同样的三个例子官网也都有说明,详见http://greenrobot.org/greendao/documentation/joins/

 QueryBuilder<Teacher> queryBuilder = daoSession.getTeacherDao().queryBuilder();
        queryBuilder.join(Student.class, StudentDao.Properties.TId)
        .where(StudentDao.Properties.Name.like ("%1%"));
       // queryBuilder.where(TeacherDao.Properties.Name.like("%11%"));
        List<Teacher> querytechers= queryBuilder.list();

第二种实现方式,不使用多表关联使用单表的查询。先找到对应的学生类,然后再遍历通过上面的getTeacher方法找到对应的老师对象集合。

    List<Student>  students= daoSession.getStudentDao().queryBuilder().where(StudentDao.Properties.Name.like("%1%")).list();
    List<Teacher> querytechers= getTeacher(students);


   private List<Teacher> getTeacher(List<Student> students) {
        List<Teacher> teachers= new ArrayList<>();
        for (int i = 0; i < students.size(); i++) {
            teachers.add(students.get(i).getTeacher());
        }
        return teachers;
    }

当然如果处理的数据场景简单,其实不用使用多表,就在字段中添加分隔符存储,后面再对查询的数据做处理。

当然这里还有个问题就是会出现查询的数据有重复,所以这里需要去重,由于某些场景是需要保持顺序的,所以 就采用了保持顺序的去重方法。

   private static void DuplicateRemoval(List<Teacher> ioList)
    {
        LinkedHashSet<Teacher> tmpSet = new LinkedHashSet<Teacher>(ioList.size());
        tmpSet.addAll(ioList);
        ioList.clear();
        ioList.addAll(tmpSet);
    }

以上就是多表联合查询的一些小小总结,希望能够对读者有所帮助。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值