Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
  • Mybatis-Plus
  • Mybatis
    • 参数获取
      • $与#区别
      • 一个参数
      • 多个参数
      • 实体类参数
    • CRUD
    • 动态SQL
      • if
      • where
      • set
      • foreach
      • choose/when/otherwise
    • ResultMap
      • 基本使用
      • 自动映射
      • 继承映射关系
    • 多表查询
      • 多对一
      • 一对多
  • 手写Mybatis

  • 常见面试题
  • Mybatis
Nreal
2024-01-12
目录

Mybatis

# 参数获取

# $与#区别

${}的本质就是字符串拼接,#{}的本质就是占位符赋值 ;

  • ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;

    传入的数据直接显示生成在sql中;无法防止sql注入;

  • #{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号;

    传入的数据都生成一个字符串,自动传入的数据加一个双引号;能够防止sql注入;

# 一个参数

  1. 根据 id 查找

    User findById(Integer id);
    
    1
    <select id="findById" resultType="**.User">  
        select * from user where id = #{id}
    </select>
    
    1
    2
    3
  2. 根据 属性名 查找

    User findByUser(User user);
    
    1
    <select id="findByUser" resultType="**.User">
        select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}
    </select>
    
    1
    2
    3
  3. 根据 Map 中的Key获取对应值

    User findByMap(Map map);
    
    1
    <select id="findByMap" resultType="**.User">
        select * from user where id = #{id} and username = #{username} and age = #{age} and address = #{address}
    </select>
    
    1
    2
    3

    接口中调用:

    Map map = new HashMap();
    map.put("id",2);
    map.put("username","PDD");
    map.put("age",25);
    map.put("address","上海");
    userDao.findByMap(map);
    
    1
    2
    3
    4
    5
    6

# 多个参数

Mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中;

在方法参数前使用@Param来设置参数名;

接口中定义:

User findByCondition(@Param("id") Integer id,@Param("username") String username);
1
<select id="findByCondition" resultType="**.User">
     select * from user where id = #{id} and username = #{username}
</select>
1
2
3

# 实体类参数

@Test
public void insertUser() {
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
	User user = new User(null,"Tom","123456",12,"男","123@321.com");
	mapper.insertUser(user);
}
1
2
3
4
5
6
7
<!--int insertUser(User user);-->
<insert id="insertUser">
	insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
1
2
3
4

# CRUD

  1. 增

    void insertUser(User user);
    
    1
    <insert id="insertUser">
        insert into user values(null,#{username},#{age},#{address})
    </insert>
    
    1
    2
    3
  2. 删

    void deleteById(Integer id);
    
    1
    <delete id="deleteById">
        delete from user where id = #{id}
    </delete>
    
    1
    2
    3
  3. 改

    void updateUser(User user);
    
    1
    <!--更新用户-->
    <update id="updateUser">
        UPDATE USER SET age = #{age} , username = #{username},address = #{address} WHERE id = #{id}
    </update>
    
    1
    2
    3
    4
  4. 查

    根据 id 查询

    User findById(Integer id);
    
    1
    <select id="findById" resultType="**.User">
      select * from user where id = #{id}
    </select>
    
    1
    2
    3

    查询所有

    List<User> findAll();
    
    1
    <select id="findAll" resultType="**.User">
      select * from user
    </select>
    
    1
    2
    3

# 动态SQL

# if

<select id="findByCondition" resultType="**.User">
     select * from user
     where  id = #{id}
    <if test="username!=null">
       and username = #{username}
    </if>
</select>
1
2
3
4
5
6
7

如果参数username为null则执行的sql为:select * from user where id = ?

如果参数username不为null则执行的sql为:select * from user where id = ? and username = ?

在test属性中表示参数的时候不需要写#{};

# where

<select id="findByCondition" resultType="**.User">
    select * from user
    <where>
        <if test="id!=null">
            id = #{id}
        </if>
        <if test="username!=null">
            and username = #{username}
        </if>
    </where>
</select>
1
2
3
4
5
6
7
8
9
10
11

如果id和username都为null,则执行的sql为:**select * from user **

如果id为null,username不为null,则执行的sql为:**select * from user where username = ? **

# set

<update id="updateUser">
    UPDATE USER
    <set>
        <if test="username!=null">
            username = #{username},
        </if>
        <if test="age!=null">
            age = #{age},
        </if>
        <if test="address!=null">
            address = #{address},
        </if>
    </set>
    where id = #{id}
</update>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果调用方法时传入的User对象的id为2,username不为null,其他属性都为null:

最终执行的sql为:UPDATE USER SET username = ? where id = ?

# foreach

遍历集合或者数组类型的参数,获取其中的元素拿来动态的拼接SQL语句;

List<User> findByIds(@Param("ids") Integer[] ids);
1

如果期望动态的根据实际传入的数组的长度拼接SQL语句,例如:

select * from User WHERE id in( ? , ? , ? , ?, ? ) 
1
<select id="findByIds" resultType="**.User">
    select * from User
    <where>
        <foreach collection="ids" open="id in(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </where>
</select>
1
2
3
4
5
6
7
8

collection:表示要遍历的参数;

open:表示遍历开始时拼接的语句;

item:表示给当前遍历到的元素的取的名字;

separator:表示每遍历完一次拼接的分隔符;

close:表示最后一次遍历完拼接的语句;

# choose/when/otherwise

  • choose类似于java中的switch
  • when类似于java中的case
  • otherwise类似于java中的dufault

接口中方法定义如下:

List<User> selectChose(User user);
1

期望:

​ 如果user对象的id不为空时就通过id查询;

​ 如果id为null,username不为null就通过username查询;

​ 如果id和username都会null就查询id为3的用户;

<select id="selectChose" resultType="**.User">
    select * from user
    <where>
        <choose>
            <when test="id!=null">
                id = #{id}
            </when>
            <when test="username!=null">
                username = #{username}
            </when>
            <otherwise>
                id = 3
            </otherwise>
        </choose>
    </where>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# ResultMap

# 基本使用

自定义结果集和实体类属性的映射规则;

<!--
    resultMap 用来自定义结果集和实体类的映射
        属性:
            id 相当于这个resultMap的唯一标识
            type 用来指定映射到哪个实体类
    id标签  用来指定主键列的映射规则
        属性:
            property 要映射的属性名
            column  对应的列名
    result标签 用来指定普通列的映射规则
        属性:
            property 要映射的属性名
            column 对应的列名
-->
<resultMap id="orderMap" type="**.Order" >
    <id column="id" property="id"></id>
    <result column="createtime" property="createtime"></result>
    <result column="price" property="price"></result>
    <result column="remark" property="remark"></result>
    <result column="user_id" property="userId"></result>
</resultMap>

<!--使用我们自定义的映射规则-->
<select id="findAll" resultMap="orderMap">
    SELECT id,createtime,price,remark,user_id  FROM ORDERS
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 自动映射

默认开启,如果结果集的列名和属性名相同是会自动映射的,只需要写特殊情况的映射关系即可;

下面这种写法和上面的写法会有相同的效果,因为其他属性的属性名和结果集的列名都是相同的会自动映射:

<resultMap id="orderMap" type="**.Order" >
    <result column="user_id" property="userId"></result>
</resultMap>
<!--使用我们自定义的映射规则-->
<select id="findAll" resultMap="orderMap">
    SELECT id,createtime,price,remark,user_id  FROM ORDERS
</select>
1
2
3
4
5
6
7

如有需要可以选择关闭自动映射可以把resultMap的autoMapping属性设置为false:

<resultMap id="orderMap" type="**.Order" autoMapping="false">
    <id column="id" property="id"></id>
    <result column="createtime" property="createtime"></result>
    <result column="price" property="price"></result>
    <result column="remark" property="remark"></result>
    <result column="user_id" property="userId"></result>
</resultMap>
1
2
3
4
5
6
7

# 继承映射关系

resultMap的extends属性来指定一个resultMap,从而复用重复的映射关系配置;

<!--定义个父映射,供其他resultMap继承-->
<resultMap id="baseOrderMap" type="**.Order" >
    <id column="id" property="id"></id>
    <result column="createtime" property="createtime"></result>
    <result column="price" property="price"></result>
    <result column="remark" property="remark"></result>
</resultMap>
<!--继承baseOrderMap,然后只需要写自己特有的映射关系即可-->
<resultMap id="orderMap" type="**.Order" autoMapping="false" extends="baseOrderMap">
    <result column="user_id" property="userId"></result>
</resultMap>
1
2
3
4
5
6
7
8
9
10
11

# 多表查询

员工表&部门表,各有对方字段;

# 多对一

  1. 级联方式:

    <resultMap id="empAndDeptResultMapOne" type="Emp">
    	<id property="eid" column="eid"></id>
    	<result property="empName" column="emp_name"></result>
    	<result property="age" column="age"></result>
    	<result property="sex" column="sex"></result>
    	<result property="email" column="email"></result>
    	<result property="dept.did" column="did"></result>
    	<result property="dept.deptName" column="dept_name"></result>
    </resultMap>
    <!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
    	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
    </select>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  2. association

    • association:处理多对一的映射关系;
    • property:需要处理多对的映射关系的属性名;
    • javaType:该属性的类型;
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
    	<id property="eid" column="eid"></id>
    	<result property="empName" column="emp_name"></result>
    	<result property="age" column="age"></result>
    	<result property="sex" column="sex"></result>
    	<result property="email" column="email"></result>
    	<association property="dept" javaType="Dept">
    		<id property="did" column="did"></id>
    		<result property="deptName" column="dept_name"></result>
    	</association>
    </resultMap>
    <!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
    	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
    </select>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

# 一对多

collection方式:

  • collection:用来处理一对多的映射关系;
  • ofType:表示该属性对应的集合中存储的数据的类型;
<resultMap id="DeptAndEmpResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
	<collection property="emps" ofType="Emp">
		<id property="eid" column="eid"></id>
		<result property="empName" column="emp_name"></result>
		<result property="age" column="age"></result>
		<result property="sex" column="sex"></result>
		<result property="email" column="email"></result>
	</collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
	select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Mybatis-Plus
常见面试题

← Mybatis-Plus 常见面试题→

Theme by Vdoing | Copyright © 2021-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式