12、动态SQL

什么是动态SQL?

  动态 SQL 是 MyBatis 的强大特性之一。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

环境搭建:

依赖:

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.11</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.30</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

1、创建sql

CREATE TABLE `t_car`  (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键自增',
  `car_num` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车编号',
  `brand` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车品牌',
  `guide_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '厂家指导价',
  `produce_time` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '生产日期',
  `car_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车类型,包括:燃油车,电车,氢能源',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_car
-- ----------------------------
INSERT INTO `t_car` VALUES (1, '100', '宝马520Li', 41.00, '2022-09-01', '燃油车');
INSERT INTO `t_car` VALUES (2, '101', '奔驰E300L', 54.00, '2022-08-01', '电车');
INSERT INTO `t_car` VALUES (5, '103', '丰田', 25.80, '2022-01-01', '燃油车');
INSERT INTO `t_car` VALUES (7, '104', '比亚迪汉', 10.00, '2022-11-17', '电车');
INSERT INTO `t_car` VALUES (8, '105', '奥迪', 35.50, '2022-11-11', '燃油车');

SET FOREIGN_KEY_CHECKS = 1;

2、Mybatis配置文件:resource/mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="db.properties"/>
    <!--日志-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--设置实体类别名-->
    <typeAliases>
        <package name="com.zhixi.pojo"/>
    </typeAliases>
    <!--数据连接池-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/CarMapper.xml"/>
    </mappers>
</configuration>
View Code

3、数据库连接信息:resource/db.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjpowernode-mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
jdbc.username=root
jdbc.password=zhixi158

4、Mybatis工具类:com.zhixi.utils.MabatisUtil

package com.zhixi.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**
 * @ClassName MybatisUtil
 * @Author zhangzhixi
 * @Description
 * @Date 2022-11-18 10:37
 * @Version 1.0
 */

public class MybatisUtil {

    /**
     * 线程工厂
     */
    private static SqlSessionFactory sqlSessionFactory;

    /**
     * 保证事务
     */
    private static final ThreadLocal<SqlSession> THREAD_LOCAL = new ThreadLocal<>();


    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接通道
     *
     * @return sqlSession操作数据库
     */
    public static SqlSession openSession() {
        SqlSession sqlSession = THREAD_LOCAL.get();

        if (sqlSession == null) {
            sqlSession = sqlSessionFactory.openSession();
            THREAD_LOCAL.set(sqlSession);
        }
        return sqlSession;
    }

    /**
     * 关闭连接对象
     * @param sqlSession SQL会话
     */
    public static void close(SqlSession sqlSession){
        if (THREAD_LOCAL.get() != null) {
            sqlSession.close();
            THREAD_LOCAL.remove();
        }
    }

}
View Code

5、实体类:com.zhixi.pojo.Car

package com.zhixi.pojo;

import lombok.Builder;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * 
 * @TableName t_car
 */
@Builder
public class Car implements Serializable {
    /**
     * 主键自增
     */
    private Long id;

    /**
     * 汽车编号
     */
    private String carNum;

    /**
     * 汽车品牌
     */
    private String brand;

    /**
     * 厂家指导价
     */
    private BigDecimal guidePrice;

    /**
     * 生产日期
     */
    private String produceTime;

    /**
     * 汽车类型,包括:燃油车,电车,氢能源
     */
    private String carType;

    private static final long serialVersionUID = 1L;

    /**
     * 主键自增
     */
    public Long getId() {
        return id;
    }

    /**
     * 主键自增
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * 汽车编号
     */
    public String getCarNum() {
        return carNum;
    }

    /**
     * 汽车编号
     */
    public void setCarNum(String carNum) {
        this.carNum = carNum;
    }

    /**
     * 汽车品牌
     */
    public String getBrand() {
        return brand;
    }

    /**
     * 汽车品牌
     */
    public void setBrand(String brand) {
        this.brand = brand;
    }

    /**
     * 厂家指导价
     */
    public BigDecimal getGuidePrice() {
        return guidePrice;
    }

    /**
     * 厂家指导价
     */
    public void setGuidePrice(BigDecimal guidePrice) {
        this.guidePrice = guidePrice;
    }

    /**
     * 生产日期
     */
    public String getProduceTime() {
        return produceTime;
    }

    /**
     * 生产日期
     */
    public void setProduceTime(String produceTime) {
        this.produceTime = produceTime;
    }

    /**
     * 汽车类型,包括:燃油车,电车,氢能源
     */
    public String getCarType() {
        return carType;
    }

    /**
     * 汽车类型,包括:燃油车,电车,氢能源
     */
    public void setCarType(String carType) {
        this.carType = carType;
    }

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Car other = (Car) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getCarNum() == null ? other.getCarNum() == null : this.getCarNum().equals(other.getCarNum()))
            && (this.getBrand() == null ? other.getBrand() == null : this.getBrand().equals(other.getBrand()))
            && (this.getGuidePrice() == null ? other.getGuidePrice() == null : this.getGuidePrice().equals(other.getGuidePrice()))
            && (this.getProduceTime() == null ? other.getProduceTime() == null : this.getProduceTime().equals(other.getProduceTime()))
            && (this.getCarType() == null ? other.getCarType() == null : this.getCarType().equals(other.getCarType()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getCarNum() == null) ? 0 : getCarNum().hashCode());
        result = prime * result + ((getBrand() == null) ? 0 : getBrand().hashCode());
        result = prime * result + ((getGuidePrice() == null) ? 0 : getGuidePrice().hashCode());
        result = prime * result + ((getProduceTime() == null) ? 0 : getProduceTime().hashCode());
        result = prime * result + ((getCarType() == null) ? 0 : getCarType().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", carNum=").append(carNum);
        sb.append(", brand=").append(brand);
        sb.append(", guidePrice=").append(guidePrice);
        sb.append(", produceTime=").append(produceTime);
        sb.append(", carType=").append(carType);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}
View Code

6、mapper接口:com.zhixi.mapper.CarMapper

package com.zhixi.mapper;

import com.zhixi.pojo.Car;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author zhixi
 * @description 针对表【t_car】的数据库操作Mapper
 * @createDate 2022-11-19 22:36:54
 * @Entity com.zhixi.pojo.Car
 */
public interface CarMapper {

    /**
     * 查询所有的记录
     *
     * @return 汽车集合
     */
    List<Car> selectAllCar();

    /**
     * 按照条件进行查询,最多只能够有一个条件成立
     *
     * @param carNum  品牌编号
     * @param brand   品牌名称
     * @param carType 车辆类型
     * @return 查询到的数据结果
     */
    List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType);

    /**
     * 批量删除-in
     *
     * @param ids id数组
     * @return 删除的记录条数
     */
    int deleteByIdsToIn(@Param("ids") Long[] ids);

    /**
     * 批量删除-or
     *
     * @param ids id数组
     * @return 删除的记录条数
     */
    int deleteByIdsToOr(@Param("ids") Long[] ids);

    /**
     * 根据多条件查询Car
     * @param brand 品牌名称
     * @param guidePrice 品牌价格
     * @param carType 品牌类型
     * @return 查询集合列表
     */
    List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") BigDecimal guidePrice, @Param("carType") String carType);

    /**
     * 插入汽车
     * @param car 汽车记录
     * @return =1表示插入成功,否则失败
     */
    int insertSelective(Car car);

    /**
     * 根据id更新car
     * @param car 汽车实体
     * @return  =1表示更新成功,否则失败
     */
    int updateByPrimaryKey(Car car);

    /**
     * 批量添加,使用foreach标签
     * @param cars 汽车集合
     * @return 插入条数
     */
    int insertBatchByForeach(@Param("cars") List<Car> cars);
}
View Code

7、Mapper-SQL文件:resource/CarMapper.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">
<mapper namespace="com.zhixi.mapper.CarMapper">

    <resultMap id="BaseResultMap" type="com.zhixi.pojo.Car">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="carNum" column="car_num" jdbcType="VARCHAR"/>
        <result property="brand" column="brand" jdbcType="VARCHAR"/>
        <result property="guidePrice" column="guide_price" jdbcType="DECIMAL"/>
        <result property="produceTime" column="produce_time" jdbcType="CHAR"/>
        <result property="carType" column="car_type" jdbcType="VARCHAR"/>
    </resultMap>


    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from t_car
        where id = #{id,jdbcType=BIGINT}
    </select>

    <select id="selectAllByMap" resultType="java.util.Map">
        select
        <include refid="Base_Column_List"/>
        from t_car
    </select>

    <sql id="Base_Column_List">
        id,car_num,brand,
        guide_price,produce_time,car_type
    </sql>
    <select id="selectAllCar" resultType="com.zhixi.pojo.Car">
        select
        <include refid="Base_Column_List"/>
        from t_car;
    </select>

    <select id="selectCarByChoose" resultType="com.zhixi.pojo.Car">
        select
        <include refid="Base_Column_List"/>
        from t_car
        <where>
            <choose>
                <when test="carNum!=null and carNum!=''">
                    car_num = #{carNum,jdbcType=VARCHAR}
                </when>
                <when test="brand!=null and brand!=''">
                    brand = #{brand,jdbcType=VARCHAR}
                </when>
                <otherwise>
                    car_type = #{carType,jdbcType=VARCHAR}
                </otherwise>
            </choose>
        </where>
    </select>
    <select id="selectByMultiCondition" resultType="com.zhixi.pojo.Car">
        select
        <include refid="Base_Column_List"/>
        from t_car
        <where>
            <if test="brand != null and brand != ''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                and guide_price >= #{guidePrice}
            </if>
            <if test="carType != null and carType != ''">
                and car_type = #{carType}
            </if>
        </where>
    </select>

    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
        delete
        from t_car
        where id = #{id,jdbcType=BIGINT}
    </delete>
    <delete id="deleteByIdsToIn">
        delete
        from t_car
        where id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
    <delete id="deleteByIdsToOr">
        delete
        from t_car
        where
        <foreach collection="ids" item="id" separator="or">
            id = #{id}
        </foreach>
    </delete>
    <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car" useGeneratedKeys="true">
        insert into t_car
        ( id, car_num, brand
        , guide_price, produce_time, car_type)
        values ( #{id,jdbcType=BIGINT}, #{carNum,jdbcType=VARCHAR}, #{brand,jdbcType=VARCHAR}
               , #{guidePrice,jdbcType=DECIMAL}, #{produceTime,jdbcType=CHAR}, #{carType,jdbcType=VARCHAR})
    </insert>
    <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car"
            useGeneratedKeys="true">
        insert into t_car
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null">id,</if>
            <if test="carNum != null">car_num,</if>
            <if test="brand != null">brand,</if>
            <if test="guidePrice != null">guide_price,</if>
            <if test="produceTime != null">produce_time,</if>
            <if test="carType != null">car_type,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id,jdbcType=BIGINT},</if>
            <if test="carNum != null">#{carNum,jdbcType=VARCHAR},</if>
            <if test="brand != null">#{brand,jdbcType=VARCHAR},</if>
            <if test="guidePrice != null">#{guidePrice,jdbcType=DECIMAL},</if>
            <if test="produceTime != null">#{produceTime,jdbcType=CHAR},</if>
            <if test="carType != null">#{carType,jdbcType=VARCHAR},</if>
        </trim>
    </insert>
    <insert id="insertBatchByForeach">
        insert into t_car values
        <foreach collection="cars" item="car" separator=",">
            (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
        </foreach>
    </insert>
    <update id="updateByPrimaryKey" parameterType="com.zhixi.pojo.Car">
        update t_car
        <set>
            <if test="carNum != null">
                car_num = #{carNum,jdbcType=VARCHAR},
            </if>
            <if test="brand != null">
                brand = #{brand,jdbcType=VARCHAR},
            </if>
            <if test="guidePrice != null">
                guide_price = #{guidePrice,jdbcType=DECIMAL},
            </if>
            <if test="produceTime != null">
                produce_time = #{produceTime,jdbcType=CHAR},
            </if>
            <if test="carType != null">
                car_type = #{carType,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=BIGINT};
    </update>
</mapper>
View Code

标签的使用:

resultMap标签

查询结果的列名和java对象的属性名对应不上怎么办?

  • 第一种方式:as 给列起别名
  • 第二种方式:使用resultMap进行结果映射
  • 第三种方式:是否开启驼峰命名自动映射(配置settings)

为什么会出现resultMap标签?

/**
 * 查询所有的记录
 *
 * @return 汽车集合
 */
List<Car> selectAllCar();

因为我们在查询数据的时候,可能遇到实体类的属性名跟数据库的列名不一致的情况,比如car_num与实体类属性carNum对不上的情况,这时候查询到的数据为null。

第一种解决办法:as起别名  

<select id="selectAllCar" resultType="com.zhixi.pojo.Car">
    select id,
           car_num as carNum,
           brand,
           guide_price as guidePrice,
           produce_time as produceTime,
           car_type as carType
    from t_car;
</select>

第二种(推荐):resultMap

就是将数据库属性与实体类属性做一一对应

<resultMap id="BaseResultMap" type="com.zhixi.pojo.Car">
    <id property="id" column="id" jdbcType="BIGINT"/>
    <result property="carNum" column="car_num" jdbcType="VARCHAR"/>
    <result property="brand" column="brand" jdbcType="VARCHAR"/>
    <result property="guidePrice" column="guide_price" jdbcType="DECIMAL"/>
    <result property="produceTime" column="produce_time" jdbcType="CHAR"/>
    <result property="carType" column="car_type" jdbcType="VARCHAR"/>
</resultMap>

然后将select标签中的resultType换成resultMap="BaseResultMap"即可

第三种:是否开启驼峰自动映射

使用这种方式的前提是:属性名遵循Java的命名规范,数据库表的列名遵循SQL的命名规范。

Java命名规范:首字母小写,后面每个单词首字母大写,遵循驼峰命名方式。

SQL命名规范:全部小写,单词之间采用下划线分割。

比如以下的对应关系:

如何启用该功能,在mybatis-config.xml文件中进行配置:

<!--放在properties标签后面-->
<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

sql标签与include标签

sql标签用来声明sql片段

include标签用来将声明的sql片段包含到某个sql语句当中

作用:代码复用。易维护。

<sql id="Base_Column_List">
    id,car_num,brand,
    guide_price,produce_time,car_type
</sql>
<select id="selectAllCar" resultType="com.zhixi.pojo.Car">
    select <include refid="Base_Column_List"/>
    from t_car;
</select>

where if标签

提供了可选的查找文本功能。

  where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。

  而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

需求:多条件查询。

可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)

/**
 * 按照条件进行查询,最多只能够有一个条件成立
 * @param carNum 品牌编号
 * @param brand 品牌名称
 * @param carType 车辆类型
 * @return 查询到的数据结果
 */
List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType);
/**

<select id="selectByMultiCondition" resultType="com.zhixi.pojo.Car">
    select
    <include refid="Base_Column_List"/>
    from t_car
    <where>
        <if test="brand != null and brand != ''">
            and brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice != null and guidePrice != ''">
            and guide_price >= #{guidePrice}
        </if>
        <if test="carType != null and carType != ''">
            and car_type = #{carType}
        </if>
    </where>
</select>

测试:

@Test
public void testSelectByMultiCondition() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Car> cars = mapper.selectByMultiCondition("宝马", new BigDecimal("25"), "燃油车");
    cars.forEach(System.out::println);
}

trim标签

trim标签的属性:

  • prefix:在trim标签中的语句前添加内容
  • suffix:在trim标签中的语句后添加内容
  • prefixOverrides:前缀覆盖掉(去掉)
  • suffixOverrides:后缀覆盖掉(去掉)
/**
 * 插入汽车
 * @param car 汽车记录
 * @return =1表示插入成功,否则失败
 */
int insertSelective(Car car);


<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car" useGeneratedKeys="true"> insert into t_car <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="carNum != null">car_num,</if> <if test="brand != null">brand,</if> <if test="guidePrice != null">guide_price,</if> <if test="produceTime != null">produce_time,</if> <if test="carType != null">car_type,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null">#{id,jdbcType=BIGINT},</if> <if test="carNum != null">#{carNum,jdbcType=VARCHAR},</if> <if test="brand != null">#{brand,jdbcType=VARCHAR},</if> <if test="guidePrice != null">#{guidePrice,jdbcType=DECIMAL},</if> <if test="produceTime != null">#{produceTime,jdbcType=CHAR},</if> <if test="carType != null">#{carType,jdbcType=VARCHAR},</if> </trim> </insert>

测试:

@Test
public void testInsertSelective() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Car car = Car.builder().
            carNum("106")
            .brand("奥迪A8L")
            .guidePrice(new BigDecimal("85.00")).
            produceTime("2018-08-01").carType("燃油车").
            build();
    int i = mapper.insertSelective(car);
    System.out.println(i);
    sqlSession.commit();
    sqlSession.close();
}

set标签

主要使用在update语句当中,用来生成set关键字,同时去掉最后多余的“,”

比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。

/**
 * 根据id更新car
 * @param car 汽车实体
 * @return  =1表示更新成功,否则失败
 */
int updateByPrimaryKey(Car car);

<update id="updateByPrimaryKey" parameterType="com.zhixi.pojo.Car">
    update t_car
    <set>
        <if test="carNum != null">
            car_num = #{carNum,jdbcType=VARCHAR},
        </if>
        <if test="brand != null">
            brand = #{brand,jdbcType=VARCHAR},
        </if>
        <if test="guidePrice != null">
            guide_price = #{guidePrice,jdbcType=DECIMAL},
        </if>
        <if test="produceTime != null">
            produce_time = #{produceTime,jdbcType=CHAR},
        </if>
        <if test="carType != null">
            car_type = #{carType,jdbcType=VARCHAR},
        </if>
    </set>
    where id = #{id,jdbcType=BIGINT};
</update>

测试:

@Test
public void testUpdateByPrimaryKey() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Car car = Car.builder()
            .id(9L)
            .brand("奥迪A4L")
            .guidePrice(new BigDecimal("35.00")).
            build();
    /*
        执行的SQL:
        ==>  Preparing: update t_car SET brand = ?, guide_price = ? where id = ?;
        ==> Parameters: 奥迪A4L(String), 35.00(BigDecimal), 9(Long)
        <==    Updates: 1
     */
    int i = mapper.updateByPrimaryKey(car);
    System.out.println(i);
    sqlSession.commit();
    sqlSession.close();
}

choose、when、otherwise

  有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

匹配顺序是从第一个进行选择,第一个成立就执行第一个中的匹配,
如果第一个第二个数据都匹配的话,还是按第一个中的执行。

语法格式:

<choose>
  <when></when>
  <when></when>
  <when></when>
  <otherwise></otherwise>
</choose>

需求:

  先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。

/**
 * 按照条件进行查询,最多只能够有一个条件成立
 *
 * @param carNum  品牌编号
 * @param brand   品牌名称
 * @param carType 车辆类型
 * @return 查询到的数据结果
 */
List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType);

<select id="selectCarByChoose" resultType="com.zhixi.pojo.Car">
    select
    <include refid="Base_Column_List"/>
    from t_car
    <where>
        <choose>
            <when test="carNum!=null and carNum!=''">
                car_num = #{carNum,jdbcType=VARCHAR}
            </when>
            <when test="brand!=null and brand!=''">
                brand = #{brand,jdbcType=VARCHAR}
            </when>
            <otherwise>
                car_type = #{carType,jdbcType=VARCHAR}
            </otherwise>
        </choose>
    </where>
</select>

测试:

@Test
public void testSelectCarByChoose() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    /*
        ==>  Preparing: select id,car_num,brand, guide_price,produce_time,car_type from t_car WHERE car_num = ?
        ==> Parameters: 103(String)
        <==    Columns: id, car_num, brand, guide_price, produce_time, car_type
        <==        Row: 5, 103, 丰田, 25.80, 2022-01-01, 燃油车
        <==      Total: 1
     */
    List<Car> cars = mapper.selectCarByChoose("103", "丰田", null);
    cars.forEach(System.out::println);
}

foreach标签

场景

批量删除:

delete from t_car where id in(1,2,3);
delete from t_car where id = 1 or id = 2 or id = 3;

批量添加:

insert into t_car values
  (null,'1001','凯美瑞',35.0,'2010-10-11','燃油车'),
  (null,'1002','比亚迪唐',31.0,'2020-11-11','新能源'),
  (null,'1003','比亚迪宋',32.0,'2020-10-11','新能源')

批量删除:使用in  

/**
 * 批量删除
 *
 * @param ids id数组
 * @return 删除的记录条数
 */
int deleteByIdsToIn(@Param("ids") Long[] ids);

<delete id="deleteByIdsToIn">
    delete
    from t_car
    where id in
    <foreach collection="ids" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</delete>

测试:

@Test
public void testDeleteByIds() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Long[] ids = {1L, 2L};
    /*
        ==>  Preparing: delete from t_car where id in ( ? , ? )
        ==> Parameters: 1(Long), 2(Long)
        <==    Updates: 2
     */
    int delNum = mapper.deleteByIdsToIn(ids);
    System.out.println(delNum);
    sqlSession.commit();
    sqlSession.close();
}

批量删除:使用or

/**
 * 批量删除-or
 *
 * @param ids id数组
 * @return 删除的记录条数
 */
int deleteByIdsToOr(@Param("ids") Long[] ids);

<delete id="deleteByIdsToOr">
    delete
    from t_car
    where
    <foreach collection="ids" item="id" separator="or">
        id = #{id}
    </foreach>
</delete>

测试:

@Test
public void testDeleteByIdsToOr() {
    SqlSession sqlSession = MybatisUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Long[] ids = {5L, 6L};
    /*
        ==>  Preparing: delete from t_car where id = ? or id = ?
        ==> Parameters: 5(Long), 6(Long)
        <==    Updates: 2
     */
    int delNum = mapper.deleteByIdsToOr(ids);
    System.out.println(delNum);
    sqlSession.commit();
    sqlSession.close();
}

批量添加:

 /**
  * 批量添加,使用foreach标签
  * @param cars 汽车集合
  * @return 插入条数
  */
 int insertBatchByForeach(@Param("cars") List<Car> cars);

<insert id="insertBatchByForeach">
    insert into t_car values
    <foreach collection="cars" item="car" separator=",">
        (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
    </foreach>
</insert>

测试:

@Test
public void testInsertBatchByForeach(){
    CarMapper mapper = MybatisUtil.openSession().getMapper(CarMapper.class);
    Car car1 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车");
    Car car2 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车");
    Car car3 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车");
    List<Car> cars = Arrays.asList(car1, car2, car3);
    /*
        ==>  Preparing: insert into t_car values (null,?,?,?,?,?) , (null,?,?,?,?,?) , (null,?,?,?,?,?)
        ==> Parameters: 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String), 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String), 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String)
        <==    Updates: 3
     */
    int count = mapper.insertBatchByForeach(cars);
    System.out.println("插入了几条记录" + count);
    MybatisUtil.openSession().commit();
    MybatisUtil.openSession().close();
}

 

 

posted @ 2020-12-30 20:30  Java小白的搬砖路  阅读(156)  评论(0编辑  收藏  举报