一、Mybatis常用标签

1、mapper.xml文件

(1)mapper.xml文件概述

mapper接口的缺点:

接口中注释的写法是硬编码,不易于后期的维护,如果类中的属性名和数据库中的名字不一样则无相应的值,在实际项目中不推荐使用。

mapper接口的方法

mapper.xml文件是mybatis中定义的sql映射的文件,相对于mapper接口的优势是(方便):

  • 易于维护和管理,语法结构易读,方便进行调整、重构和扩展
  • 易于定义分离关注原则(通过把SQL逻辑和业务逻辑分离)
  • 分离SQL逻辑和业务逻辑有利于代码的模块化开发

(2)Mapper.xml文件的结构

mapper_xml文件结构

示例:

首先需要配置文件:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/coolsharkhub?useSSL=false&serverTimeZone=Asia/Shanghai
spring.datasource.name=root
spring.datasource.password=root
logging.level.cn.highedu.boot3.mapper=debug

mybatis.mapper-locations=classpath:mapper/*.xml

建立实体类:

/**
 * @document: 商品类别实体类
 * 对应数据库中category表
 * @Author:SmallG
 * @CreateTime:2023/9/5+9:51
 */

public class Category {
    private Long id;
    private String name;
    private Boolean display;
    private Integer orderNum;
    private LocalDateTime create;
    private LocalDateTime update;

   省略...
}

mapper接口:

@Mapper
public interface CategoryMapper {
    /**
     * 根据id查询商品类别
     */
    Category getCategoryById(long id);
}

CategoryMapper.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="cn.highedu.boot3.mapper.CategoryMapper">
    <select id="getCategoryById" resultType="cn.highedu.boot3.entity.Category">
        select * from category where id = #{id}
    </select>
</mapper>

测试文件:

@SpringBootTest //声明这是一个springboot的测试类
class CategoryMapperTest {
    @Autowired
    CategoryMapper categoryMapper;
    @Test
    void getCategoryById() {
        Category category = categoryMapper.getCategoryById(1L);
        System.out.println(category);
    }
}

访问流程:

程序执行过程

(3)下划线映射驼峰

修改一下配置文件:

#把数据库的下划线标识转换为类中的驼峰标识
mybatis.configuration.map-underscore-to-camel-case=true

2、Mybatis基础标签

(1)增删改查标签

共同的属性:

  • id:指定标签对应的抽象方法的名称,是标签的必要属性,同一个Mapper.xml文件中不能有两个标签拥有相同的id值
  • parameterType:输入参数的类型
  • statementType:指定是否使用预处理语句,可选值为 STATEMENT、PREPARED、CALLABLE,默认为 PREPARED

特殊的属性:

1、select标签

  • resultType:指定查询结果的数据类型,适用于查询结果与Java类完全匹配的情况
  • resultMap:指定查询结果映射的规则,适用于查询结果不能直接映射到某个Java类的情况

2、insert标签

  • useGeneratedKeys:表示是否使用自动生成的主键,默认为false。如果设置为true,则在插入数据时会返回主键值
  • keyProperty:表示将自动生成的主键值赋值给哪个属性,需要与useGeneratedKeys一起使用

先写方法,后写操作

添加商品

编写mapper接口中的方法:

/**
 * 保存一条商品类别记录
 * @return 返回受影响的行数
 */
int insertCategory(Category category);

编写mapper.xml文件中的操作代码:

<!-- useGeneratedKeys返回生成的主键 -->
<insert id="insertCategory" useGeneratedKeys="true">
    insert into category (name, order_num)
    values (#{name}, #{orderNum})
</insert>
删除商品

mapper添加代码:

/**
 * 根据id删除一条商品类别记录
 * @param id 传入的id值
 * @return 返回受影响的行数
 */
int deleteCategoryById(long id);

mapper.xml添加代码:

<!-- 删除一条商品类别记录 -->
<delete id="deleteCategoryById">
    delete from category where id=#{id}
</delete>

测试代码:

@Test
void deleteCategoryById() {
    int result = categoryMapper.deleteCategoryById(8L);
    if (result>0){
        System.out.println("成功删除了"+result+"条记录");
    } else {
        System.out.println("删除失败!");
    }
}
修改商品

mapper接口添加代码:

/**
* 根据id修改display的值
* @param id 传入的id
* @return 返回受影响的行数
*/
int updateDisplayById(@Param("display") Integer display,@Param("id") long id);

mapper.xml配置文件添加代码:

<!-- 根据id修改display的值 -->
<update id="updateDisplayById">
    update category set display=#{display} where id=#{id}
</update>

测试代码:

@Test
void updateDisplayById() {
    int result = categoryMapper.updateDisplayById(0,5L);
    if (result>0){
        System.out.println("成功修改了"+result+"条数据");
    }else {
        System.out.println("修改失败");
    }
}
查询商品

mapper接口代码:

/**
 * 查询
 * @return
 */
List<Category> listAllCategory();

mapper.xml代码:

<select id="listAllCategory" resultType="cn.highedu.boot3.entity.Category">
    select * from category
</select>

测试代码:

@Test
void listAllCategory() {
    List<Category> categories = categoryMapper.listAllCategory();
    //函数式引用
    categories.forEach(System.out::println);
}

(2)模糊查询

正常思路

mapper接口:

/**
 * 根据名字模糊查询商品类别
 * @param name 商品类别名称
 * @return
 */
List<Category> listByName(String name);

mapper.xml代码:

<!-- 模糊查询 -->
<select id="listByName" resultType="cn.highedu.boot3.entity.Category">
    select * from category where name like #{name}
</select>

测试代码:

@Test
void listByName() {
    List<Category> categories = categoryMapper.listByName("%精品%");
    categories.forEach(System.out::println);
}
改良查询(推荐使用)

mapper接口部分代码:

/**
 * 根据名字模糊查询商品类别
 * @param name 商品类别名称
 * @return
 */
List<Category> listByName(String name);

mapper.xml部分代码:

<!-- 模糊查询 -->
<select id="listByName" resultType="cn.highedu.boot3.entity.Category">
    select * from category where name like concat('%',#{name},'%')
</select>

测试代码:

@Test
void listByName() {
    List<Category> categories = categoryMapper.listByName("精品");
    categories.forEach(System.out::println);
}

(3)resultMap标签

查询的结果无法简单的映射到一个Java类时(实体类的名称和数据库中的字段名不一致),可以使用resultMap标签。

public class UserLog {
    private Long id;
    private Long userId;
    private String optType;
    private LocalDateTime create;   //数据库字段gmt_create
    private LocalDateTime modified; //数据库字段gmt_modified
    
    省略...get...set...构造...toString...
}

mapper接口:

@Mapper
public interface UserLogMapper {
    /**
     * 查询所有的用户日志
     */
    List<UserLog> listAll();
}

mapper.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="cn.highedu.boot3.mapper.UserLogMapper">
    <!--  定义一个结果映射,主要是为了解决类中的属性名和数据库中的字段名不一致问题  -->
    <resultMap id="UserLogMap" type="cn.highedu.boot3.entity.UserLog">
        <!-- 主键映射 -->
        <id column="id" property="id"></id>
        <!-- 普通字段映射 -->
        <!-- column表示数据库中的字段名 property表示类中的属性名 -->
        <result column="user_id" property="userId"></result>
        <result column="otp_type" property="optType"></result>
        <result column="gmt_create" property="create"></result>
        <result column="gmt_modified" property="modified"></result>
    </resultMap>

    <select id="listAll" resultMap="UserLogMap">
        select * from user_log
    </select>
</mapper>

测试类:

@SpringBootTest
class UserLogMapperTest {
    @Autowired
    UserLogMapper userLogMapper;

    @Test
    void listAll() {
        List<UserLog> list = userLogMapper.listAll();
        list.forEach(System.out::println);
    }
}

3、封装关联查询结果

(1)association标签

’<‘association’>‘ 标签是用于定义对象之间关联关系的标签,主要用于处理一对一(One-to-One)的关联查询结果映射。“标签是用于定义对象之间关联关系的标签,主要用于处理一对一(One-to-One)的关联查询结果映射。

association标签的属性如下:

  • property:指定Java类中的属性名,用于关联查询结果中的对应字段
  • column:指定查询结果集合中的字段名
  • javaType:指定关联的Java类型,代表关联属性的数据类型
多对一关系映射

创建实体:

/**
 * @document: 商品实体类 对应数据库表product
 * @Author:SmallG
 * @CreateTime:2023/9/5+15:12
 */

public class Product {
    private Long id;
    private String title;
    private String image;
    private Double discount;
    private Double price;
    private Integer sales;
    private Integer stock;
    private Integer views;
    private LocalDateTime created;//创建时间
    private LocalDateTime updated; //修改时间
    private Category category; //类别属性 对应数据库category_id;
     省略...   
}

mapper接口:

@Mapper
public  interface ProductMapper {
    /**
     * 根据商品id查询商品
     * @param id
     * @return
     */
    Product getById(Long id);
}

mapper.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="cn.highedu.boot3.mapper.ProductMapper">
    <!-- 结果映射 -->
    <resultMap id="ProductMap" type="cn.highedu.boot3.entity.Product">
        <id column="id" property="id"></id>
        <result column="title" property="title"></result>
        <result column="image" property="image"></result>
        <result column="discount" property="discount"></result>
        <result column="price" property="price"></result>
        <result column="sales" property="sales"></result>
        <result column="stock" property="stock"></result>
        <result column="views" property="views"></result>
        <result column="created" property="created"></result>
        <result column="updated" property="updated"></result>
        <!--多对一关系-->
        <!--property是类中的属性名,column是数据库的字段名-->
        <!--javaType是类中属性的类型-->
        <association property="category" column="category_id" javaType="cn.highedu.boot3.entity.Category">
            <!--Category类中的属性与Category表的映射关系-->
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
            <result column="display" property="display"></result>
            <result column="order_num" property="orderNum"></result>
            <result column="created" property="created"></result>
            <result column="updated" property="updated"></result>
        </association>

    </resultMap>
    <!--根据id查询一件商品信息-->
    <select id="getById" resultMap="ProductMap">
        select p.id,
               p.title,
               image,
               discount,
               price,
               sales,
               stock,
               category_id,
               views,
               p.created,
               p.updated,
               c.id,
               name,
               display,
               order_num,
               c.created,
               c.updated
        from product p
                 join category c on p.category_id = c.id
        where p.id = #{id}
    </select>

</mapper>

(2)封装一对多查询结果

关联查询中一对多查询的结果,对应到Java类中一般在【一】的一方采用List集合的方式,关联【多】的一方的对象的集合。

在类别中添加对应的所有商品

一对多查询

在categoryMapper.xml中添加resultMap:

collection标签用于实现集合类型属性的自动封装。

 <resultMap id="categoryMap" type="cn.highedu.boot3.entity.Category">
        <!--Category类中的属性与Category表的映射关系-->
        <result column="name" property="name"></result>
        <result column="display" property="display"></result>
        <result column="order_num" property="orderNum"></result>
        <result column="created" property="created"></result>
        <result column="updated" property="updated"></result>
        <!--property是类中的属性  ofType是集合中数据的类型-->
        <collection property="products" ofType="cn.highedu.boot3.entity.Product">
            <!--Product映射关系-->
            <id column="id" property="id"></id>
            <result column="title" property="title"></result>
            <result column="image" property="image"></result>
            <result column="discount" property="discount"></result>
            <result column="price" property="price"></result>
            <result column="sales" property="sales"></result>
            <result column="stock" property="stock"></result>
            <result column="views" property="views"></result>
            <result column="created" property="created"></result>
            <result column="updated" property="updated"></result>
        </collection>
    </resultMap>

 <!--  根据类别id查询商品信息  -->
    <select id="getByIdWithProducts" resultMap="CategoryMap">
        select p.id,
               p.title,
               image,
               discount,
               price,
               sales,
               stock,
               category_id,
               views,
               p.created,
               p.updated,
               c.id,
               name,
               display,
               order_num,
               c.created,
               c.updated
        from product p
                 join category c on p.category_id = c.id
        where c.id = #{id}
    </select>

CategoryMapper接口添加方法:

/**
 * 根据id查询一个类别,同时查询出该类别所有的商品信息
 * @param id 类别id
 * @return 类别对象 包含商品的集合
 */
Category getByIdWithProducts(Long id);

测试方法:

@Test
void getByIdWithProducts() {
    Category category = categoryMapper.getByIdWithProducts(2L);
    System.out.println(category);
    //查看类中 的products集合
    category.getProducts().forEach(System.out::println);
}

(3)复用SQL语句(开发普遍应用)

<!--  根据类别id查询商品信息  -->
<select id="getByIdWithProducts" resultMap="CategoryMap">
    <!--使用sql片段 include(包含)-->
    <include refid="queryProductAndCategory"></include>
    where c.id =#{id}
</select>
<!--  一段公共的sql片段,任何地方都可以引用  -->
<sql id="queryProductAndCategory">
    select p.id,
           p.title,
           image,
           discount,
           price,
           sales,
           stock,
           category_id,
           views,
           p.created,
           p.updated,
           c.id,
           c.name,
           display,
           order_num,
           c.created,
           c.updated
    from product p
             join category c on p.category_id = c.id
</sql>

二、动态SQL

1、动态sql概述

在查询的时候根据业务需求有些条件有时传有时不传,sql语句可能产生动态变化,动态sql可以通过不同的条件产生不同的sql语句。

MyBatis提供了多种动态SQL标签,较为常用的四种如下所示:

1、if标签:用于判断某个条件是否满足,如果满足则执行某些操作。

2、choose标签:类似于Java中的switch语句,根据某个条件选择不同的分支,可以配合when和otherwise(除此以外)标签使用。

3、foreach标签:用于遍历集合(如List、Map等),根据集合中的元素动态构建SQL语句。

4、where标签:用于动态生成where语句,当where语句为空时,不会加入到最终的SQL语句中。

where和if标签示例

添加ProductMapper接口中的方法:

/**
 * 商品信息查询 多条件查询 查询条件不股东
 *
 * @param title    商品标题---模糊查询
 * @param minPrice 最小商品价格---范围查询
 * @param maxPrice 最大商品价格
 * @return 满足条件的所有商品
 */
List<Product> listProduct(@Param("title") String title,
                          @Param("minPrice") Double minPrice,
                          @Param("maxPrice") Double maxPrice);

mapper.xml查询语句:

<select id="listProduct" resultMap="ProductMap">
        select *
        from product
        <!--where标签可以保证sql语句的正确性-->
        <!--如果一个条件都不满足会智能的去掉where关键字 还可以去掉多余的and关键字-->
        <where>
            <!--if表示条件判断,test写具体逻辑 条件满足sql语句中加上相应的条件-->
            <!--title不等于空值并且不能等于空字符串-->
            <if test="title != null and title !=''">
                title like concat('%',#{title},'%')
            </if>
            <!--&gt;表示大于符号 &lt;表示小于符号-->
            <if test="minPrice != null">
                and price &gt;= #{minPrice}
            </if>
            <if test="maxPrice != null">
                and price &lt;= #{maxPrice}
            </if>
        </where>
</select>

测试代码:

@Test
void listProduct() {
    //查询是没有maxPrice条件
    List<Product> products = productMapper.listProduct("男",50.0,null);
    products.forEach(System.out::println);
}

when标签示例

需求:开发一个查询商品列表的方法,接收字符串类型的orderType作为参数。其中:

  • 如果传入的参数为“sales”,则按照销量降序排列
  • 如果传入的参数为“views”,则按照浏览量降序排列
  • 其他情况下,按stock库存量降序排列

mapper接口:

/**
 * 根据不同的排序类别 查询后的商品数据
 * @param orderType 根据价格流量销量排序
 * @return 返回
 */
List<Product> listProductByOrder(String orderType);

xml配置文件:

<!--查询具有排序的商品信息-->
<select id="listProductByOrder" resultMap="ProductMap">
    select *
    from product
    order by
    <!--多分支 choose类似于java的switch-->
    <choose>
        <!--相当于case-->
        <when test="orderType == 'price'">
            price
        </when>
        <when test="orderType == 'views'">
            views
        </when>
        <when test="orderType == 'sales'">
            sales
        </when>
    </choose>
</select>
@Test
void listProductByOrder() {
    productMapper.listProductByOrder("sales").forEach(System.out::println);
}

效果展示:

when效果展示

foreach标签示例

需求:开发一个查询商品的方法,接收Integer类型的集合作为参数,查询商品类别的id值与集合中数据值相同的商品信息。

mapper接口添加方法:

/**
 * 根据商品id查多件商品
 * @return
 */
List<Product> listProductByIds(@Param("ids") List<Integer> ids);

xml文件:

<!--根据多个id查询多个商品-->
<select id="listProductByIds" resultMap="ProductMap">
    select *
    from product
    <if test="ids != null and ids.size() > 0">
        where id in
        <!--item为每个元素起个别名-->
        <!--open 开始标识-->
        <!--close 结束标识-->
        <!--separator分割-->
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </if>
</select>

测试代码:

@Test
void listProductByIds() {
    productMapper.listProductByIds(List.of(2,3,4)).forEach(System.out::println);
}

效果展示:

foreach效果展示

set标签示例

mapper接口添加方法:

/**
 * 修改类别的名称、display(是否显示)、orderNum(展示顺序)其中几个
 * @param category
 * @return
 */
int updateBySet(@Param("category") Category category);

xml添加操作:

<update id="updateBySet">
    update category
    <set>
        <!--category.name(OGNL - 对象导航语言,默认调用对象相应的get方法取值)-->
        <if test="category.name != null">
            name=#{category.name},
        </if>
        <if test="category.display != null">
            display=#{category.display},
        </if>
        <if test="category.orderNum != null">
            order_num=#{category.orderNum}
        </if>
    </set>
    where id = #{category.id}
</update>

测试方法:

@Test
void updateBySet() {
    Category category = categoryMapper.getCategoryById(5L);
    category.setName("ABC");
    category.setDisplay(false);
    category.setOrderNum(8);
    int i = categoryMapper.updateBySet(category);
    if (i > 0) {
        System.out.println("修改成功");
    } else {
        System.out.println("修改失败");
    }
}

效果展示:

修改成功

三、练习

1 MyBatis关联查询练习

请在Homework项目下新建一个Module,该Module为一个Spring Boot项目,命名为ssm_hw03,作为今天的课后作业项目。

首先,将课前资料中的sample1.sql文件中的数据导入到数据库中的ssm_hw01db数据库中。

表格的字段及关系如图所示:

练习1

表中的样例数据如图所示:

练习2

请基于上述数据库表和数据,在ssm_hw03项目中实现如下需求:

1、开发查询全部角色数据的方法,关联查询角色的坐骑数据。

2、开发查询全部国家数据的方法,关联查询该国家中的全部角色数据。

3、开发查询全部战役的方法,关联查询参加过该战役的全部角色数据。

提示:

1、仅需要完成持久层的开发和测试即可,必须有测试用例。

2、持久层可以仅声明一个HWMapper接口,对应HWMapper.xml文件。

实体类:

/**
 * @document: 战役实体类
 * @Author:SmallG
 * @CreateTime:2023/9/5+18:36
 */

public class Battle {
    private Integer id;
    private String name;
    private List<Character> characters;

       省略...
}

/**
 * @document: 角色实体类
 * @Author:SmallG
 * @CreateTime:2023/9/5+18:35
 */

public class Character {
    private Integer id;
    private String name;
    private Horse horse;

    省略...
}

/**
 * @document: 国家实体类
 * @Author:SmallG
 * @CreateTime:2023/9/5+18:36
 */

public class Country {
    private Integer id;
    private String name;
    private List<Character> characters;

       省略...
}

/**
 * @document: 坐骑实体类
 * @Author:SmallG
 * @CreateTime:2023/9/5+18:36
 */

public class Horse {
    private Integer id;
    private String name;

      省略...
}

mapper接口:

@Mapper
public interface HWMapper {

    /**
     * 开发查询全部角色数据的方法,关联查询角色的坐骑数据。
     * @return
     */
    List<Character> getAll();

    /**
     * 开发查询全部国家数据的方法,关联查询该国家中的全部角色数据。
     * @return
     */
    List<Country> getAllCountry();

    /**
     * 查询全部战役的方法,关联查询参加过该战役的全部角色数据。
     * @return
     */
    List<Battle> getBattle();
}

mapper.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.example.ssm_hw03.mapper.HWMapper">
    <resultMap id="getAllMap" type="com.example.ssm_hw03.entity.Character">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <association property="horse" javaType="com.example.ssm_hw03.entity.Horse">
            <id column="hid" property="id"></id>
            <result column="hname" property="name"></result>
        </association>
    </resultMap>
    <select id="getAll" resultMap="getAllMap">
        select t.id, t.name, h.id as hid, h.name as hname
        from t_character t
                 join horse h on t.hid = h.id
    </select>

    <resultMap id="getAllCountry" type="com.example.ssm_hw03.entity.Country">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="characters" ofType="com.example.ssm_hw03.entity.Character">
            <id column="cid" property="id"></id>
            <result column="cname" property="name"></result>
            <association property="horse" javaType="com.example.ssm_hw03.entity.Horse">
                <id column="hid" property="id"></id>
                <result column="hname" property="name"></result>
            </association>
        </collection>

    </resultMap>
    <select id="getAllCountry" resultMap="getAllCountry">
        select c1.id, c1.name, c2.id as cid, c2.name as cname, h.id as hid, h.name as hname
        from country c1
                 join t_character c2 on c1.id = c2.cid
                 join horse h on h.id = c2.hid
    </select>


    <resultMap id="getBattleMap" type="com.example.ssm_hw03.entity.Battle">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="characters" ofType="com.example.ssm_hw03.entity.Character">
            <id column="tid" property="id"></id>
            <result column="tname" property="name"></result>
            <association property="horse" javaType="com.example.ssm_hw03.entity.Horse">
                <id column="hid" property="id"></id>
                <result column="hname" property="name"></result>
            </association>

        </collection>
    </resultMap>
    <select id="getBattle" resultMap="getBattleMap">
        select b.id, b.name, t.id as tid, t.name as tname, h.id as hid, h.name as hname
        from battle b
                 join character_battle c on b.id = c.bid
                 join t_character t on c.cid = t.id
                 join horse h on h.id = t.hid;
    </select>
</mapper>

测试类:

@SpringBootTest
class HWMapperTest {
    @Autowired
    HWMapper mapper;

    @Test
    void getAll() {
        List<Character> all = mapper.getAll();
        all.forEach(System.out::println);
    }

    @Test
    void getAllCountry() {
        mapper.getAllCountry().forEach(System.out::println);
    }

    @Test
    void getBattle() {
        mapper.getBattle().forEach(System.out::println);
    }
}

2 MyBatis动态SQL练习

首先,将课前资料中的sample2.sql文件中的数据导入到数据库中的ssm_hw01db数据库中。

表格的字段及数据如图所示:

练习3

请基于上述数据库表和数据,在ssm_hw03项目中实现如下需求:

1、开发一个查询员工的方法:接收firstName, lastName和jobTitle三个参数,如果传入的参数不为null且不为空字符串,则使用该参数作为模糊查询的条件;如果传入的参数均为null,则默认查询全部员工信息。

2、开发一个查询员工的方法,接收字符串类型的startYear作为参数,格式为yyyy,如果传入的参数不为null且不为空字符串,则查询在startYear之后入职的员工,否则查询自2018年起入职的员工。

3、开发一个查询员工的方法,接收Integer类型的集合作为参数,查询员工的id值与集合中数据值相同的员工信息。

提示:

1、仅需要完成持久层的开发和测试即可,必须有测试用例。

2、持久层为EmployeeMapper接口,对应EmployeeMapper.xml文件。

实体类:

/**
 * @document: 员工实体类
 * @Author:SmallG
 * @CreateTime:2023/9/5+21:33
 */

public class Employee {
    private Integer id;
    private String firstName;
    private String lastName;
    private Date dateOfBirth;
    private Date hireDate;
    private String jobTitle;

       省略...
}

mapper接口:

@Mapper
public interface EmployeeMapper {

    /**
     * 接收firstName, lastName和jobTitle三个参数,
     * 如果传入的参数不为null且不为空字符串,则使用该参数作为模糊查询的条件;
     * 如果传入的参数均为null,则默认查询全部员工信息。
     *
     * @param firstName
     * @param lastName
     * @param jobTitle
     * @return
     */
    List<Employee> getEmployee1(@Param("firstName") String firstName,
                                @Param("lastName") String lastName,
                                @Param("jobTitle") String jobTitle);

    /**
     * 查询在指定年份及之后入职的员工
     * 默认查询自2018年起入职的员工
     *
     * @return
     */
    List<Employee> listEmployeeByYear(String startYear);

    /**
     * 查询ID与ids集合中数据值相同的员工信息
     * 默认不返回任何信息
     * 注意,必须添加@Param注解
     *
     * @return
     */
    List<Employee> listEmployeeByIds(@Param("ids") List<Integer> ids);

}

mapper.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.example.ssm_hw03.mapper.EmployeeMapper">
    <resultMap id="EmployeeMap" type="com.example.ssm_hw03.entity.Employee">
        <id property="id" column="id"></id>
        <result column="first_name" property="firstName"></result>
        <result column="last_name" property="lastName"></result>
        <result column="date_of_birth" property="dateOfBirth"></result>
        <result column="hire_Date" property="hireDate"></result>
        <result column="job_title" property="jobTitle"></result>
    </resultMap>
    <select id="getEmployee1" resultMap="EmployeeMap">
        select *
        from employee
        <where>
            <if test="firstName !=null and firstName != ''">
                and firstName like concat('%',#{firstName},'%')
            </if>
            <if test="lastName !=null and lastName != ''">
                and lastName like concat('%',#{lastName},'%')
            </if>
            <if test="jobTitle !=null and jobTitle != ''">
                and jobTitle like concat('%',#{jobTitle},'%')
            </if>
        </where>
    </select>


    <select id="listEmployeeByYear" resultMap="EmployeeMap">
        SELECT *
        FROM employee
        where
        <choose>
            <when test="startYear!=null and startYear!=''">
                year(hire_date) >=#{startYear}
            </when>
            <otherwise>
                year(hire_date) >=2018
            </otherwise>
        </choose>
    </select>

    <select id="listEmployeeByIds" resultMap="EmployeeMap">
        SELECT * FROM employee where
        <choose>
            <when test="ids !=null and ids.size() !=0">
                id in
                <foreach collection="ids" item="id" open="(" separator="," close=")">
                    #{id}
                </foreach>
            </when>
            <otherwise>
                1=2
            </otherwise>
        </choose>
    </select>
</mapper>

测试类:

@SpringBootTest
class EmployeeMapperTest {

    @Autowired
    EmployeeMapper mapper;

    @Test
    void getEmployee1() {
        mapper.getEmployee1(null,null,null).forEach(System.out::println);
    }

    @Test
    void listEmployeeByYear() {
        String startYear = "2016";
        List<Employee> list = mapper.listEmployeeByYear(startYear);
        list.forEach(System.out::println);
    }

    @Test
    void listEmployeeByIds() {
        List<Integer> ids = List.of(1,3,5);
        List<Employee> list =mapper.listEmployeeByIds(ids);
        list.forEach(System.out::println);
    }
}
最后修改:2023 年 09 月 06 日
如果觉得我的文章对你有用,请随意赞赏