背景
上一篇文章 Android系列之GreenDao基本使用(增、删、改、查)给大家介绍的GreenDao最基本的用法。看完上篇文章之后,大家对于基本的增删改查应该都已经学会了。那么这篇文章就给大家介绍下在GreenDao中如何进行连表查询。
GreenDao内置的注解@ToMany @ToOne
连表查询无非是这三种情况:
1.一对一 @ToOne
2. 一对多 @ToMany
3. 多对多 @ToMany
//@JoinEntity注解:entity 中间表;sourceProperty 实体属性;targetProperty 外链实体属性
@ToMany
@JoinEntity(
entity = XXXX.class,
sourceProperty = "xxid",
targetProperty = "xx2id"
)
这三个注解的使用方法我就不多介绍了,感兴趣的同学可以看下这位童鞋的文章。
多表联查
其实说道这里,ORM的框架对于一些简答的查询是封装比较好的,用起来也是比较方便。但是对于一些比较复杂的SQL语句,可能这方便的支持还不如自己写SQL方便一点。
不用注解,如何自己指定连表查询
先说明下表的结构:
user_info表
字段名 | 说明 |
---|---|
id | 主键自增 |
user_name | 用户姓名 |
user_number | 用户编号 |
user_age | 用户年龄 |
level | 用户级别 |
teacher_info表
字段名 | 说明 |
---|---|
id | 主键自增 |
teacher_name | 教师姓名 |
teacher_tpye | 教师类型 |
teacher_user_merge 表(关系表)
字段名 | 说明 |
---|---|
id | 主键自增 |
user_id | 用户主键 |
teacher_id | 教师主键 |
说明:
一个学生表、一个教师表。学生和教师之间是多对多的关系。
正常情况下,我们可能需要怎么样的结果:
问题一:查询某个学生的老师
我们来分析这个sql,主体肯定是teacher_info这张表,那么学生和老师之间的关系需要通过关系表去查询,如果我们单纯的写sql的话应该是这样的:
select * from teacher_info join teacher_user_merge on teacher_user_merge .teacher_id = teacher_info._id where teacher_user_merge .user_id=2
其实也不难,就2张表联查,但是在GreenDao中该如何表现呢?
在之前的文章中写到有个QueryBuilder类,这个类中有个join方法,我们看看这个方法呢
卧槽,这个方法有四种不同的参数,如图:
这四个方法的参数也太顶了吧,完全不知道啥意思。当遇到这种情况的时候,该怎么办?一种是比较兴平气和的人点进去,看方法上的注释,如下图:
大家注意看下我画出来的部分,这就是这四个方法的区别(准确说是三个方法的区别,下面那个我也不知道啥意思)
还有一种比较呆的方法,就是直接先代码,之前不是打开了sql调试模式么,直接写,看打印出来的sql语句是什么样子就行了。
仔细看下这几个方法的参数:无非是Class<J>
类型 和Property
类。
Property
类大家一定很熟悉,就是表的属性,比如 teacher表的id
TeacherInfoTableDao.Properties.Id
Class<J>
当然就是表的class类型
再加上四级的英语水平,比如 sourceProperty
、destinationProperty
、destinationEntityClass
三个类的解释如下:
1. join(Class destinationEntityClass, Property destinationProperty)
/**
* 这是将本身表的主键id和目标表的指定字段属性进行关联也就是on 后面的字段
*/
public <J> Join<T, J> join(Class<J> destinationEntityClass, Property destinationProperty) {
return join(dao.getPkProperty(), destinationEntityClass, destinationProperty);
}
举个例子:
QueryBuilder<TeacherInfoTable> queryBuilder = DbHelper.getInstance().getDaoSession().getTeacherInfoTableDao().queryBuilder();
queryBuilder.join(TeacherUserMerge.class, TeacherUserMergeDao.Properties.TeacherId)
.where(eacherUserMergeDao.Properties.UserId.eq(2));
queryBuilder.build().list();
对应的sql
SELECT T."_id",T."teacher_name",T."teach_type" FROM "teacher_info" T JOIN teacher_user_merge J1 ON T."_id"=J1."teacher_id" WHERE J1."user_id"
2. join(Property sourceProperty, Class destinationEntityClass)
这个其实跟上面的方法很相似,不过是反过来了,指定源表的属性和目标表的主键进行关联
举个例子:
QueryBuilder<TeacherInfoTable> queryBuilder = DbHelper.getInstance().getDaoSession().getTeacherInfoTableDao().queryBuilder();
queryBuilder.join(TeacherInfoTableDao.Properties.Id, TeacherUserMerge.class).where(
TeacherUserMergeDao.Properties.UserId.eq(2));
queryBuilder.build().list();
对应的sql
SELECT T."_id",T."teacher_name",T."teach_type" FROM "teacher_info" T JOIN teacher_user_merge J1 ON T."_id"=J1."_id" WHERE J1."user_id"=?
3. join(Property sourceProperty, Class destinationEntityClass, Property destinationProperty)
这个其实跟上面的方法很相似,不过是反过来了,指定源表的属性和目标表的主键进行关联
举个例子:
QueryBuilder<TeacherInfoTable> queryBuilder2 = DbHelper.getInstance().getDaoSession().getTeacherInfoTableDao().queryBuilder();
queryBuilder2.join(TeacherInfoTableDao.Properties.Id, TeacherUserMerge.class, TeacherUserMergeDao.Properties.TeacherId).where(
TeacherUserMergeDao.Properties.UserId.eq(2));
queryBuilder2.build().list();
对应的sql
SELECT T."_id",T."teacher_name",T."teach_type" FROM "teacher_info" T JOIN teacher_user_merge J1 ON T."_id"=J1."teacher_id" WHERE J1."user_id"=?
4.家庭作业啊,这里不解释(=。=)
看完这三个方法,然后我们在回到上面的问题
查询某个学生的老师,对比下sql我们可以看到。第三种join就是我们想要的内容。(不相信的童鞋可以放到本地sql执行下)
为什么不用注解的形式去联查
第一个原因:
不知道各位有没有发现,注解使用的条件之一就是必须是有主外键关系。但在实际开发中,表和表之间的关系,都是通过代码逻辑控制,也就是数据库这一层是不加主外键的。
第二个原因:
不知为何,习惯了mybaits的这种半orm的框架,对于这种不需要自己手写sql的完全orm还是不太习惯,有些时候我宁愿自己写sql还比较快,比如我上面举得例子。sql几分钟就写好了,但是为了使用GreenDao,我得话大量的时间去学习它的用法,就比较尴尬=。=
总结
上篇文章给大家介绍了最基本的用法 Android系列之GreenDao基本使用(增、删、改、查)
感兴趣的童鞋可以了解下,如果觉得还不错,可以点播关注,谢谢。
下一篇准备给大家介绍下实际开发中,如何去使用GreenDao,以及可能会遇到的一些问题。
附上地址:Android系列之GreenDao数据升级和加密
附
GreenDao三部曲:
Android系列之GreenDao基本使用(增、删、改、查)(一)
Android系列之GreenDao连表查询(二)
Android系列之GreenDao数据升级和加密(三)