在项目中遇到多表关联查询,主要就是 一对一,一对多关联和 left join方式的对比,结合前端框架 做内容展示和搜索功能时的区别!
此处只做简单实例,就不写实体、controller和service了。
假设有2张表(pk为表主键):
user表:
pk | id | name | sex |
---|---|---|---|
userImg(用户图片)表:
pk | id | url | userId | type |
---|---|---|---|---|
1、方式一:Mybatis的一对多,一对一查询方式
为了解释和left join 的区别,一对多就是下面的one 改成 many = @Many(select = " "),
就不单独写了。
//查询userImg表 同时关联查询user表,type字段作为搜索条件
@Select(value="
<script>
select id,url,userId,type from userImg
<where>
<if test = 'type != null and type != ""'> type = #{type}</if>
</where>
</script>")
@Results({
@Result(property = "userId" , column = "userId"),//设置关联字段
@Result(property = "name" , column = "userId" ,//property 中的name 需要在userImg实体类中声明,单独查一个字段就声明一个字段,若要所有字段,也可以声明整个实体类
one = @One(select="com.test.mapper.userMapper.getUserName")) //此处为关联查询的方法路径
})
List<UserImg> getlist(UserImg userImg);
//根据上面写的查询,一般不在同一个Mapper类中,此处方便展示
@Select(value="Select name from user where id = #{userId}")
String getUserName (int userId);
此处只举例关联一个表,要关联多个表,只需在@Results里面继续增加@Result,设置好字段和代理名字、方法路径即可。
2.方式二:left join 方式
//查询userImg表 同时关联查询user表,type字段作为搜索条件,此处不同点在于多加了一个name的搜索(稍后解释)
@Select(value="
<script>
select a.id,a.url,a.userId,a.type,b.name from userImg a
left join user b on a.userId = b.id
<where>
<if test = 'type != null and type != ""'> a.type = #{type}</if>
<if test = 'name != null and type != ""'> and b.name = #{name}</if>
</where>
</script>")
List<UserImg> getlist(UserImg userImg);//同样因为用的userImg 实体接受,需要在实体中加上name字段
同样,若需要关联查多张表只需要不停的left join 就可以了。
3.总结:这两种方式的区别和优劣
简述两种方式的区别:
方式一: 本质还是分开单独去查每张表,最后拿到结果返回到实体中。
方式二: 已左表为主,查询各表相关数据然后结合涉及到的字段,排序后,形成新表返
回到实体中。
目前在项目中使用,发现了以下区别和优劣势:
①若关联的表数量较多
- 方式一相比方式二要快,表越多越明显(left join 个人建议最2张表关联用且数据量不大的时候用一用,个人亲测关联3张表时,20W+数据,自定义了排序,然后查了2分钟)
②在查询功能开发时
- 方式二比方式一友好,如果涉及到需要查询关联的表中字段时(如上代码,需要查询name时),方式一不能直接查,方式二可以直接查。
目前改善方法:
- 方式一和方式二结合使用
- 另外写一个查询方法赋值(感觉很没效率,暂时没找到其他方法,有dalao知道的话,麻烦教一下,谢谢!)