在使用mybatis的时候,碰到了多表关联的操作,现记录下来
- 查询
查询操作是遇到最多的情况,常见的是一对一,一对多,多对多
## 一对一的查询操作##
*准备工作
你需要两张用来测试的表,搭好的框架,环境 的配置等 ,表对应的实体类,如下,现有表typea,typeb,b表维护关系
对应的实体类,无非就是get,set方法,在Typeb需要有一个Typea类型作为属性
public class Typeb {
private String bname;
private int bid;
private String bicon;
private Typea typea;
}
省略get,set...
public class Typea {
private String name;
private int id;
private String img;
}
省略get,set...
*映射文件的配置
<select id="selb" parameterType="int" resultMap="br">
select
b.id as bid,
b.name as bname,
b.icon as bicon,
a.id as aid,
a.name as aname,
a.img as aimg
From typeb b left outer join typea a on b.typea=a.id
where b.id=#{id}
</select>
<resultMap type="com.siyu.vo.Typeb" id="br">
<id property="bid" column="bid"/>
<result property="bname" column="bname"/>
<result property="bicon" column="bicon"/>
<association property="typea" column="typea" resultMap="ar"/>
</resultMap>
<resultMap type="com.siyu.vo.Typea" id="ar">
<id property="id" column="aid"/>
<result property="name" column="aname"/>
<result property="img" column="aimg"/>
</resultMap>
简单说明一下,这里有两种方法可以,一是嵌套查询,会有N+1的问题,至于什么是N+1,就是执行了一条SQL语句获取了结果列表(+1)。对列表每一条记录执行查询获取细节(N)。另一种就是上面这样,嵌套结果,看一下配置。
先写上联合查询,对每一条查询记录都有清晰的重命名,接下来是映射这个结果, 使用resultMap,在映射typeb时使用association来关联typea,我将typeb分离出来可以重用,但用作简单例子时,也可以简单来写。
<resultMap type="com.siyu.vo.Typeb" id="br">
<id property="bid" column="bid"/>
<result property="bname" column="bname"/>
<result property="bicon" column="bicon"/>
<association property="typea" column="typea" javaType="com.siyu.vo.Typea">
<id property="id" column="aid"/>
<result property="name" column="aname"/>
<result property="img" column="aimg"/>
</association>
</resultMap>
这样的写法只不过是将通过id引用,写成直接嵌套,务必要加上javaType否则会抛出ReflectionException: Error instantiating null with invalid types () or values (). Cause: java.lang.NullPointerException该异常
*测试
借着SSM的框架测试一下
@RequestMapping(value="/abc.app")
public @ResponseBody Object test(){
return tyservice.find(1);//传入的参数为1
}
请求该方法后,返回结果如下
可以看到typea和typeb表中的数据都查出来了
一对多的查询
*准备
还是用上面两个表,这次我们把typea表作为1端,typeb作为n的一端,在表中插入几条数据, 然后修改实体类,在typea中加入List<Typeb> typebs属性
public class Typea {
private String name;
private int id;
private String img;
private List<Typeb> typebs;
省略get,set...
}
*配置
仍然通过嵌套结果的方式查询,因为a表中用的是list所以配置的时候用collection,他们的作用是一样的,只是为了区分,我这边直接将两个表的映射写到一个resultMap,当然也可以分开写通过id引用
<select id="sela" parameterType="int" resultMap="ar">
select
b.id as bid,
b.name as bname,
b.icon as bicon,
b.typea as typeas,
a.id as aid,
a.name as aname,
a.img as aimg
From typea a left outer join typeb b on a.id=b.typea
where a.id=#{id}
</select>
<resultMap type="com.siyu.vo.Typea" id="ar">
<id property="id" column="aid"/>
<result property="name" column="aname"/>
<result column="img" property="aimg"/>
<collection property="typebs" ofType="com.siyu.vo.Typeb">
<id column="bid" property="bid"/>
<result column="bname" property="bname"/>
<result column="bicon" property="bicon"/>
</collection>
</resultMap>
简单测试一下
@RequestMapping(value="/abc.app")
public @ResponseBody Object test(){
return tyabc.find(1)//传入的参数为1;
}
请求的结果如下,可以看到数据都显示出来了
[{"name":"英语类","id":1,"img":null,"typebs":[{"bname":"零基础自学英语","bid":1,"bicon":"img/english_image.png"},{"bname":"商务英语","bid":2,"bicon":"img/english_image.png"}]}]
- 修改.删除.添加后续补上