java成长记——mybatis关联操作增删改查

时间:2022-08-24 00:26:21

在使用mybatis的时候,碰到了多表关联的操作,现记录下来

  1. 查询
    查询操作是遇到最多的情况,常见的是一对一,一对多,多对多
    ## 一对一的查询操作##
    *准备工作
    你需要两张用来测试的表,搭好的框架,环境 的配置等 ,表对应的实体类,如下,现有表typea,typeb,b表维护关系
    java成长记——mybatis关联操作增删改查
    java成长记——mybatis关联操作增删改查
    对应的实体类,无非就是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
}

请求该方法后,返回结果如下
java成长记——mybatis关联操作增删改查
可以看到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"}]}]
  1. 修改.删除.添加后续补上