@TOC
1. resultType VS resultMap
在 resultType中,如果我们在实体类中的字段和mysql中的字段不匹配
这样我们是查不到 对应的值的,这时候我们就可以使用 resultMap
来手动进行映射
的处理
<resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
<!-- 主键映射 -->
<id column="id" property="id"></id>
<!-- 普通属性映射 -->
<result column="username" property="name"></result>
</resultMap>
<!-- 根据用户 id 查询用户 -->
<select id="getUserById" resultMap="BaseMap">
select * from userinfo where id=#{id}
</select>
2. 多表查询
2.1 一对一查询 association
⼀对⼀映射要使⽤ <association>
标签,具体实现如下(⼀篇⽂章只对应⼀个作者
):
我们在建一个文章实体类:
1. model层:
import lombok.Data;
@Data
public class ArticleInfo {
private int id;
private String title;
private String content;
private String createtime;
private String updatetime;
private int uid;
private int rcount;
private int state;
private UserInfo userInfo;
}
多加了一个 UserInfo 类
2. mapper层:
import com.example.demo.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface ArticleMapper {
//根据文章 id 获取文章
public ArticleInfo getArticleById(@Param("id") Integer id);
}
3. XML层:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 要设置是实现接口的具体包名加类名 -->
<mapper namespace="com.example.demo.mapper.ArticleMapper">
<resultMap id="BaseMap" type="com.example.demo.model.ArticleInfo">
<id column="id" property="id"></id>
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<result column="createtime" property="createtime"></result>
<result column="updatetime" property="updatetime"></result>
<result column="uid" property="uid"></result>
<result column="rcount" property="rcount"></result>
<result column="state" property="state"></result>
<association property="userInfo"
resultMap="com.example.demo.mapper.UserMapper.BaseMap"
columnPrefix="u_"></association>
</resultMap>
<select id="getArticleById" resultMap="BaseMap">
select a.*,u.id u_id,u.username u_username,u.password u_password
from articleinfo a
left join userinfo u on a.uid=u.id
where a.id=#{id}
</select>
</mapper>
4. 单元测试代码:
以上使⽤<association>
标签,表示⼀对⼀的结果映射:
-
property 属性:
指定 Article 中对应的属性,即⽤户。 -
resultMap 属性:
指定关联的结果集映射,将基于该映射配置来组织⽤户数据。 columnPrefix 属性:
绑定⼀对⼀对象时,是通过columnPrefix+association.resultMap.column 来映射结果集字段。
association.resultMap.column是指 标签中 resultMap属性,对应的结果集映射中,column字段。
注意事项:column不能省略
2.2 一对多查询 collection
跟一对一差不多,⼀对多需要使⽤<collection>
标签,⽤法和 <association>
相同,
1. model层:
import lombok.Data;
import java.util.List;
/**
* 用户实体类
*/
@Data
public class UserInfo {
private Integer id;
private String name;
private String password;
private String photo;
private String createtime;
private String updatetime;
private int state;
private List<ArticleInfo> artlist;
}
2. mapper层:
// 查询用户及用户发表的所有文章,根据用户id
public UserInfo getUserAndArticleByUid(@Param("uid") Integer uid);
3. XML层:
<mapper namespace="com.example.demo.mapper.UserMapper">
<resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
<!-- 主键映射 -->
<id column="id" property="id"></id>
<!-- 普通属性映射 -->
<result column="username" property="name"></result>
<result column="password" property="password"></result>
<result column="photo" property="photo"></result>
<result column="createtime" property="createtime"></result>
<result column="updatetime" property="updatetime"></result>
<result column="state" property="state"></result>
<collection property="artlist"
resultMap="com.example.demo.mapper.ArticleMapper.BaseMap"
columnPrefix="a_">
</collection>
</resultMap>
<select id="getUserAndArticleByUid" resultMap="BaseMap">
select u.*,a.id a_id,a.title a_title,a.content a_content,
a.createtime a_createtime,
a.updatetime a_updatetime from userinfo u left join articleinfo a
on u.id=a.uid where u.id=#{uid}
</select>
4. 单元测试代码:
3. 动态 SQL
3.1 if 标签
判断一个参数是否有值
的,如果没值,那么就会隐藏 if 中 的 SQL
就像我们在填写一些注册信息的时候,有些项可以填也可以不填,有些就是必须要填.
简单语法:
举例:添加用户
1. mapper层:
// 添加用户,添加用户时 photo是非必传参数
public int add2(UserInfo userInfo);
2. XML:
<!-- 添加用户,添加用户时 photo是非必传参数 -->
<insert id="add2">
insert into userinfo(username,password
<if test="photo!=null">
,photo
</if>
) values(#{name},#{password}
<if test="photo!=null">
,#{photo}
</if>
)
</insert>
3. 不加 photo 的测试代码:
3.2 trim 标签
最主要的作用就是:
去除 SQL 语句前后多余的某个字符
,向我们经常会在最后添加的值多加一个逗号啥的
主要语法:
1. mapper层:
// 添加用户,其中 username、password、photo 都是非必传参数,
// 但至少会传递一个参数
public int add3(UserInfo userInfo);
2. XML层:
<insert id="add3">
insert into userinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name!=null">
username,
</if>
<if test="password!=null">
password,
</if>
<if test="photo!=null">
photo
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name!=null">
#{name},
</if>
<if test="password!=null">
#{password},
</if>
<if test="photo!=null">
#{photo}
</if>
</trim>
</insert>
3. 单元测试代码:
3.3 where 标签
主要作用就是:
实现查询中的 where sql 替换的,他可以实现如果没有任何的查询条件,那么他可以因此查询中的 where sql,但是如果存在查询条件,那么会生成 where 的 sql 查询,并且使用 where 标签可以自动的去除最前面一个 and 字符
举例:根据 id 查找用户
1. mapper层:
// 根据用户 id 查询用户
public UserInfo getUserById(@Param("id") Integer id);
12
注意:
这里只返回一个,我就把数据库保留了一份
2. XML层:
<!-- 根据 id 查询用户 -->
<select id="getUserById" resultMap="BaseMap">
select * from userinfo
<where>
<if test="id!=null">
id=#{id}
</if>
</where>
</select>
3. 单元测试代码:
4. 加上 and:
注意:
and 在前面不能在后面
3.4 set 标签
主要作用就是:
在进行修改操作时
, 配合 if 来处理非必传输
的,它的特点就是会自动去除最后一个英文逗号
举例,修改数据:
1. mapper层:
int update2(UserInfo userInfo);
2. XML层:
<update id="update2">
update userinfo
<set>
<if test="name!=null">
username=#{name},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="photo!=null">
photo=#{photo}
</if>
</set>
where id=#{id}
</update>
3. 测试代码:
3.5 foreach 标签
作用主要就是:
对集合进行循环遍历
<foreach>
标签有如下属性:
collection:
绑定⽅法参数中的集合,如 List,Set,Map或数组对象item:
遍历时的每⼀个对象open:
语句块开头的字符串close:
语句块结束的字符串separator:
每次遍历之间间隔的字符串
举例:根据多个用户 id 删除用户:
1. mapper层:
int delIds(List<Integer> ids);
2. XML层:
<delete id="delIds">
delete from userinfo where id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</delete>
方便观察,我们可以加几条数据:
3. 单元测试代码: