Mybatis---CRUD案例

目录

1.目标

1.1环境准备

1.1.1Maven环境的搭建

1.1.2数据库表(tb_brand)及数据准备

1.1.3创建实体类Brand

1.1.4编写测试用例

1.1.5安装MyBatisX插件

1.2查询所有数据

1.2.1编写接口方法

1.2.2编写SQL语句

1.2.3编写测试方法

1.2.4起别名解决数据封装失败问题

1.2.5使用resultMap解决上述问题

1.2.6小结

 1.3查询详情

1.3.1编写接口方法

1.3.2编写SQL语句

1.3.3编写测试方法

1.3.4参数占位符

1.3.5parameterType使用

1.3.6SQL语句中特殊字段处理

 1.4多条件查询

1.4.1编写接口方法

1.4.2编写SQL语句

1.4.3编写测试方法

 1.4.4动态SQL

1.5单个条件(动态SQL)

1.5.1编写接口方法

1.5.2编写SQL语句

1.5.3编写测试方法

 1.6添加数据

1.6.1编写接口方法

1.6.2编写SQL语句

1.6.3编写测试方法

1.6.4添加-主键返回

1.7修改

1.7.1编写接口方法

1.7.2编写SQL语句

1.7.3编写测试方法

1.8删除一行数据

1.8.1编写接口方法

1.8.2编写SQL语句

1.8.3编写测试方法

1.9批量删除

1.9.1编写接口方法

1.9.2编写SQL语句

1.9.3编写测试方法

1.10Mybatis参数传递

1.10.1多个参数

1.11注解实现CRUD


1.目标

能够使用映射配置文件实现 CRUD 操作
能够使用注解实现 CRUD 操作

1.1环境准备

1.1.1Maven环境的搭建

文件👉Maven👉不勾选(从原型创建)👉下一步👉自主配置👉完成

设置👉搜索maven👉选择版本,覆盖用户设置文件(settings.xml),覆盖本地存储库👉应用👉确定

 

 

1.1.2数据库表(tb_brand)及数据准备

-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
    -- id 主键
    id           int primary key auto_increment,
    -- 品牌名称
    brand_name   varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered      int,
    -- 描述信息
    description  varchar(100),
    -- 状态:0:禁用  1:启用
    status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1);


SELECT * FROM tb_brand;

1.1.3创建实体类Brand

package com.itheima.pojo;

/**
 * 品牌
 *
 * alt + 鼠标左键:整列编辑
 *
 * 在实体类中,基本数据类型建议使用其对应的包装类型
 */

public class Brand {
    // id 主键
    private Integer id;
    // 品牌名称
    private String brandName;
    // 企业名称
    private String companyName;
    // 排序字段
    private Integer ordered;
    // 描述信息
    private String description;
    // 状态:0:禁用  1:启用
    private Integer status;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}

1.1.4编写测试用例

测试代码需要在 test/java 目录下创建包及测试用例。项目结构如下:

 

1.1.5安装MyBatisX插件

MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
主要功能:
XML映射配置文件 和 接口方法 间相互跳转
根据接口方法生成 statement
安装方式:
点击 file ,选择 settings ,就能看到如下图所示界面
注意:安装完毕后需要重启 IDEA

插件效果:

 

红色头绳的表示映射配置文件蓝色头绳的表示 mapper 接口。在 mapper 接口点击红色头绳的小鸟图标会自动跳转到对应的映射配置文件,在映射配置文件中点击蓝色头绳的小鸟图标会自动跳转到对应的 mapper 接口。也可以在mapper 接口中定义方法,自动生成映射配置文件中的 statement ,如图所示:

 

1.2查询所有数据

步骤:

1.编写接口方法: Mapper 接口
2.参数:无
查询所有数据功能是不需要根据任何条件进行查询的,所以此方法不需要参数。
//在BrandMapper接口中创建该方法
List<Brand> selectAll();
3. 结果: List
我们会将查询出来的每一条数据封装成一个 Brand 对象,而多条数据封装多个 Brand 对象,需要将这些对象封装到 List 集合中返回。
<!-- 在BrandMapper.xml映射文件中配置sql语句 -->
<select id="selectAll" resultType="brand">

    select * from tb_brand;

</select>
4.执行方法、测试

1.2.1编写接口方法

com.itheima.mapper 包写创建名为 BrandMapper 的接口。并在该接口中定义 List<Brand> selectAll() 方法。
pubic interface BrandMapper{

    List<Brand> selectAll();
}

1.2.2编写SQL语句

reources 下创建 com/itheima/mapper 目录结构,并在该目录下创建名为 BrandMapper.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.itheima.mapper.BrandMapper">

    <select id="selectAll" resultMap="brandResultMap">
        select *
        from tb_brand;
    </select>

</mapper>

1.2.3编写测试方法

在 MybatisTest 类中编写测试查询所有的方法

    @Test
    public void testSelectAll() throws IOException {
        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法
        List<Brand> brands = brandMapper.selectAll();
        System.out.println(brands);

        //5. 释放资源
        sqlSession.close();

    }

1.2.4起别名解决数据封装失败问题

从上面结果可以看到 brandName companyName 这两个属性的数据没有封装成功,查询 实体类 和 表中的字段 发现,在实体类中属性名是 brandName companyName ,而表中的字段名为 brand_name company_name ,如下图所示 。那么我们只需要保持这两部分的名称一致这个问题就迎刃而解。

方式一:as,我们可以在写sql语句时给这两个字段起别名,将别名定义成和属性名一致即可。

<select id="selectAll" resultType="brand">
    select
    id, brand_name as brandName, company_name as companyName, ordered,description,status
    from tb_brand;
</select>

方式二:SQL片段

将需要复用的 SQL 片段抽取到 sql 标签中
    <sql id="brand_column">
         id, brand_name as brandName, company_name as companyName, ordered, description, status
     </sql>
id 属性值是唯一标识,引用时也是通过该值进行引用。
在原 sql 语句中进行引用
使用 include 标签引用上述的 SQL 片段,而 refid 指定上述 SQL 片段的 id
     <select id="selectAll" resultType="brand">
         select
             <include refid="brand_column" />
         from tb_brand;
     </select>

1.2.5使用resultMap解决上述问题

起别名 + sql片段的方式 可以解决上述问题,但是它也存在问题。如果还有功能只需要查询部分字段,而不是查询所有字段,那么我们就需要再定义一个 SQL 片段,这就显得不是那么灵活。
那么我们也可以使用 resultMap 来定义字段和属性的映射关系的方式解决上述问题。
在映射配置文件中使用 resultMap 定义 字段 和 属性 的映射关系
    <resultMap id="brandResultMap" type="brand">
        <!--
            id:完成主键字段的映射
                column:表的列名
                property:实体类的属性名
            result:完成一般字段的映射
                column:表的列名
                property:实体类的属性名
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

SQL语句正常编写

    <select id="selectAll" resultMap="brandResultMap">
        select *
        from tb_brand;
    </select>

1.2.6小结

实体类属性 和 数据库表列名不一致,不能自动封装数据
起别名: SQL 语句中,对不一样的列名起别名,别名和实体类属性名一样
可以定义 片段,提升复用性
resultMap 定义完成不一致的属性名和列名的映射(as+SQL片段)
而我们最终选择使用 resultMap 的方式。查询映射配置文件中查询所有的 statement 书写如下:
    <!--
        id:唯一标识
        type:映射的类型,支持别名
    -->
    <resultMap id="brandResultMap" type="brand">
        <!--
            id:完成主键字段的映射
                column:表的列名
                property:实体类的属性名
            result:完成一般字段的映射
                column:表的列名
                property:实体类的属性名
        -->
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>



    <select id="selectAll" resultMap="brandResultMap">
        select *
        from tb_brand;
    </select>

mybatis的主要思路:

获取sqlSession对象,调用该对象中的getMapper()传入BrandMapper.Class参数即反射过去一个BrandMapper接口成为一个接口对象,该接口中有List<Brand> selectAll();方法,该方法的方法名就是BrandMapper.xml映射文件中的id名(selectAll),然后sqlSession对象执行该映射文件中的sql语句,并且返回一个List集合,元素类型为Brand。

 1.3查询详情

步骤:

编写接口方法: Mapper 接口
Brand SelectById(int id);

参数:id

查看详情就是查询某一行数据,所以需要根据id进行查询。而id以后是由页面传递过来。

结果: Brand
根据 id 查询出来的数据只要一条,而将一条数据封装成一个 Brand 对象即可
编写 SQL 语句: SQL 映射文件
<select id="selectById"parameterType="int" resultType="brand">

    select * from tb_brand where id = #{id};
</select>
执行方法、进行测试

1.3.1编写接口方法

BrandMapper 接口中定义根据id查询数据的方法

Brand selectById(int id);

1.3.2编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement ,使用 resultMap 而不是使用 resultType
<select id="selectById" resultMap="brandResultMap"> 
select * from tb_brand where id = #{id}; 
</select>

1.3.3编写测试方法

 @Test
    public void testSelectById() throws IOException {
        //接收参数
        int id = 1;

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法
        Brand brand = brandMapper.selectById(id);
        System.out.println(brand);

        //5. 释放资源
        sqlSession.close();

    }
执行测试方法结果如下:

 

1.3.4参数占位符

查询到的结果很好理解就是 id 1 的这行数据。而这里我们需要看控制台显示的 SQL 语句,能看到使用?进行占位。说明我们在映射配置文件中的写的 #{id} 最终会被?进行占位。接下来我们就聊聊映射配置文件中的参数占位符。
mybatis 提供了两种参数占位符:
#{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是 PreparedStatement。
${} :拼接SQL。底层使用的是 Statement ,会存在SQL注入问题。如下图将 映射配置文件中的 #{} 替换成 ${} 来看效果。
<select id="selectById" resultMap="brandResultMap"> 
select * from tb_brand where id = ${id}; 
</select>

 注意:从上面两个例子可以看出,以后开发我们使用 #{} 参数占位符。

1.3.5parameterType使用

对于有参数的 mapper 接口方法,我们在映射配置文件中应该配置 ParameterType 来指定参数类型。只不过该属性都可以
省略。如下图:
<select id="selectById" parameterType="int" resultMap="brandResultMap"> s
elect * from tb_brand where id = ${id}; 
</select>

1.3.6SQL语句中特殊字段处理

可以看出报错了,因为映射配置文件是 xml 类型的问题,而 > < 等这些字符在 xml 中有特殊含义,所以此时我们需要将这些符号进行转义,可以使用以下两种方式进行转义。

 转义字符与<![CDATA[特殊符号]]>

 1.4多条件查询

步骤:

编写接口方法
参数:所有查询条件
结果: List
在映射配置文件中编写 SQL 语句
编写测试方法并执行

1.4.1编写接口方法

BrandMapper 接口中定义多条件查询的方法。
而该功能有三个参数,我们就需要考虑定义接口时,参数应该如何定义。 Mybatis 针对多参数有多种实现:
方式一:使用 @Param(" 参数名称 ") 标记每一个参数,在映射配置文件中就需要使用 #{ 参数名称 } 进行占位。
List<Brand> selectByCondition(@Param("status") int status, 
@Param("companyName") String companyName,@Param("brandName") String brandName);

方式二将多个参数封装成一个实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{} 时,里面的内容必须和实体类属性名保持一致。

List<Brand> selectByCondition(Brand brand);

方式三将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和map集合中键的名称一致。

List<Brand> selectByCondition(Map map);

1.4.2编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement ,使用 resultMap 而不是使用 resultType。
因为实体类属性名与数据库属性名不一致,故使用resultMap标签。
<select id="selectByCondition" resultMap="brandResultMap"> 
select * 
from tb_brand 
where status = #{status} 
and company_name like #{companyName} 
and brand_name like #{brandName} 
</select>

1.4.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
@Test
    public void testSelectByCondition() throws IOException {
        //接收参数
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";

        // 处理参数
        companyName = "%" + companyName + "%";
        brandName = "%" + brandName + "%";

        //封装对象
       /* Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);*/

        Map map = new HashMap();
        // map.put("status" , status);
        map.put("companyName", companyName);
        // map.put("brandName" , brandName);

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法

        //List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
//        List<Brand> brands = brandMapper.selectByCondition(brand);
        List<Brand> brands = brandMapper.selectByCondition(map);
        System.out.println(brands);

        //5. 释放资源
        sqlSession.close();

    }

 1.4.4动态SQL

上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,这个时候我们的 SQL语句就不能那样写的。Mybatis 对动态 SQL 有很强大的支撑:

标签一:if

if 标签:条件判断
test 属性:逻辑表达式
    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        where

            <if test="status != null">
                and status = #{status}
            </if>
            <if test="companyName != null and companyName != '' ">
                and company_name like #{companyName}
            </if>
            <if test="brandName != null and brandName != '' ">
                and brand_name like #{brandName}
            </if>

    </select>
这种SQL语句就会根据传递的参数值进行动态的拼接。但假设第一个if不成立,则第二个if中的and则会报错,则这时候可以使用where标签解决。

标签二:where 标签

作用:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键字
    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        /* where 1 = 1*/
        <where>

            <if test="status != null">
                and status = #{status}
            </if>
            <if test="companyName != null and companyName != '' ">
                and company_name like #{companyName}
            </if>
            <if test="brandName != null and brandName != '' ">
                and brand_name like #{brandName}
            </if>
        </where>

    </select>

注意:需要给每个条件前都加上 and 关键字。

1.5单个条件(动态SQL)

 

在查询时只能选择 品牌名称 当前状态 企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态 SQL语句。
这种需求需要使用到 choose (when otherwise )标签 实现, 而 choose 标签类似于 Java 中的 switch 语句。
方式三:choose(when,otherwise)
作用:
 
choose类似于switch
when类似于case
otherwise类似于default

1.5.1编写接口方法

BrandMapper 接口中定义单条件查询的方法。
List<Brand> selectByConditionSingle(Brand brand);

1.5.2编写SQL语句

BrandMapper.xml 映射配置文件中编写 statement ,使用 resultMap 而不是使用 resultType
    <select id="selectByConditionSingle" resultMap="brandResultMap">
        select *
        from tb_brand
        <where><!--where标签可以替换where关键字,并且在所有参数没有值则不加where关键字-->
            <choose><!--相当于switch-->
                <when test="status != null"><!--相当于case-->
                    status = #{status}
                </when>
                <when test="companyName != null and companyName != '' "><!--相当于case-->
                    company_name like #{companyName}
                </when>
                <when test="brandName != null and brandName != ''"><!--相当于case-->
                    brand_name like #{brandName}
                </when>

            </choose>
        </where>
    </select>

1.5.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
@Test
    public void testSelectByConditionSingle() throws IOException {
        //接收参数
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";

        // 处理参数
        companyName = "%" + companyName + "%";
        brandName = "%" + brandName + "%";

        //封装对象
        Brand brand = new Brand();
        //brand.setStatus(status);
        brand.setCompanyName(companyName);
        //brand.setBrandName(brandName);

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法

        //List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
//        List<Brand> brands = brandMapper.selectByCondition(brand);

        List<Brand> brands = brandMapper.selectByConditionSingle(brand);
        System.out.println(brands);

        //5. 释放资源
        sqlSession.close();

    }
执行测试方法结果如下:

 1.6添加数据

步骤:

编写接口方法

void add(Brand brand);

参数:除了id之外的所有的数据。id对应的是表中主键值,而主键我们是 自动增长 生成的。

编写 SQL 语句
    <insert id="add">
        insert into tb_brand (brand_name, company_name, ordered, description, status)
        values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});

    </insert>
编写测试方法并执行

1.6.1编写接口方法

BrandMapper 接口中定义添加方法。
void add(Brand brand);

1.6.2编写SQL语句

BrandMapper.xml 映射配置文件中编写添加数据的 statement
    <insert id="add">
        insert into tb_brand (brand_name, company_name, ordered, description, status)
        values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});

    </insert>

1.6.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
@Test
    public void testAdd() throws IOException {
        //接收参数
        int status = 1;
        String companyName = "波导手机";
        String brandName = "波导";
        String description = "手机中的战斗机";
        int ordered = 100;


        //封装对象
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);
        brand.setDescription(description);
        brand.setOrdered(ordered);

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法

        brandMapper.add(brand);

        //提交事务
        sqlSession.commit();

        //5. 释放资源
        sqlSession.close();

    }
执行结果如下:

​注意:MyBatis框架是对JDBC的封装,MyBatis中的事务控制方式其本质也是JDBCsetAutoCommit()方法来设置事务提交的方式的。故需要手动提交事务,但也可以在
SqlSession sqlSession = sqlSessionFactory.openSession(true);设置自动提交事务。

1.6.4添加-主键返回

在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长)。
比如:添加订单和订单项,如下图就是京东上的订单

订单数据存储在订单表中,订单项存储在订单项表中。
添加订单数据
我们将上面添加品牌数据的案例中映射配置文件里 statement 进行修改,如下
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        insert into tb_brand (brand_name, company_name, ordered, description, status)
        values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});

    </insert>
insert 标签上添加如下属性:
useGeneratedKeys:是够获取自动增长的主键值。 true 表示获取
keyProperty 指定将获取到的主键值封装到哪儿个属性里
通过以上两个属性的设定,可以将自增长的id绑定到对象brand上面,从而方便以后信息的获取

1.7修改

在修改页面,用户在该页面书写需要修改的数据,点击 提交 按钮,就会将数据库中对应的数据进行修改。注意一 点,如果哪儿个输入框没有输入内容,我们是将表中数据对应字段值替换为空白还是保留字段之前的值?答案肯定是保留之 前的数据。

1.7.1编写接口方法

BrandMapper 接口中定义修改方法。
void update(Brand brand);
上述方法参数 Brand 就是封装了需要修改的数据,而 id 肯定是有数据的,这也是和添加方法的区别。

1.7.2编写SQL语句

BrandMapper.xml 映射配置文件中编写修改数据的 statement
    <update id="update">
        update tb_brand
        <set>
            <if test="brandName != null and brandName != ''">
                brand_name = #{brandName},
            </if>
            <if test="companyName != null and companyName != ''">
                company_name = #{companyName},
            </if>
            <if test="ordered != null">
                ordered = #{ordered},
            </if>
            <if test="description != null and description != ''">
                description = #{description},
            </if>
            <if test="status != null">
                status = #{status}
            </if>
        </set>
        where id = #{id};
    </update>
set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。

1.7.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
@Test
    public void testUpdate() throws IOException {
        //接收参数
        int status = 0;
        String companyName = "波导手机";
        String brandName = "波导";
        String description = "波导手机,手机中的战斗机";
        int ordered = 200;
        int id = 6;


        //封装对象
        Brand brand = new Brand();
        brand.setStatus(status);
//        brand.setCompanyName(companyName);
//        brand.setBrandName(brandName);
//        brand.setDescription(description);
//        brand.setOrdered(ordered);
        brand.setId(id);

        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法


        int count = brandMapper.update(brand);
        System.out.println(count);
        //提交事务
        sqlSession.commit();

        //5. 释放资源
        sqlSession.close();

    }
执行测试方法结果如下:
从结果中 SQL 语句可以看出,只修改了 status 字段值,因为我们给的数据中只给 Brand 实体对象的 status 属性设置值了。这就是 set 标签的作用。

1.8删除一行数据

通过主键 id 删除,因为 id 是表中数据的唯一标识。

1.8.1编写接口方法

BrandMapper 接口中定义根据 id 删除方法
void deleteById(int id);

1.8.2编写SQL语句

BrandMapper.xml 映射配置文件中编写删除一行数据的 statement
<delete id="deleteById">
    delete from tb_brand where id=#{id};
</delete>

1.8.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
 @Test
    public void testDeleteById() throws IOException {
        //接收参数

        int id = 6;


        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法

        brandMapper.deleteById(id);

        //提交事务
        sqlSession.commit();

        //5. 释放资源
        sqlSession.close();

    }
运行过程只要没报错,直接到数据库查询数据是否还存在。

1.9批量删除

同时删除多条数据

1.9.1编写接口方法

BrandMapper 接口中定义删除多行数据的方法。
void deleteByIds(int [] ids);//参数是一个数组,数组中存储的是多条数据的id

1.9.2编写SQL语句

BrandMapper.xml 映射配置文件中编写删除多条数据的 statement
编写 SQL 时需要遍历数组来拼接 SQL 语句。 Mybatis 提供了 foreach 标签供我们使用
foreach 标签
用来迭代任何可迭代的对象(如数组,集合)。
1.collection 属性:
mybatis 会将数组参数,封装为一个 Map 集合。
默认: array = 数组
使用 @Param 注解改变 map 集合的默认 key 的名称(arg0...)
2.item 属性:本次迭代获取到的元素。
3.separator 属性:集合项迭代之间的分隔符。 foreach 标签不会错误地添加多余的分隔符。也就是 最后一次迭代不会加 分隔符。
4.open 属性:该属性值是在拼接 SQL 语句之前拼接的语句,只会拼接一次
5.close 属性:该属性值是在拼接 SQL 语句拼接后拼接的语句,只会拼接一次
    <!--
        mybatis会将数组参数,封装为一个Map集合。
            * 默认:array = 数组
            * 使用@Param注解改变map集合的默认key的名称
    -->

    <delete id="deleteByIds">
        delete from tb_brand where id
        in
            <foreach collection="array" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
             ;
    </delete>

1.9.3编写测试方法

test/java 下的 com.itheima.mapper 包下的 MybatisTest 类中 定义测试方法
    @Test
    public void testDeleteByIds() throws IOException {
        //接收参数

        int[] ids = {5,7,8};


        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);

        //4. 执行方法

        brandMapper.deleteByIds(ids);

        //提交事务
        sqlSession.commit();

        //5. 释放资源
        sqlSession.close();

    }

1.10Mybatis参数传递

Mybatis 接口方法中可以接收各种各样的参数,如下:
多个参数
单个参数:单个参数又可以是如下类型:
        POJO 类型
        Map 集合类型
        Collection 集合类型
        
        List 集合类型
        Array 类型
        其他类型

1.10.1多个参数

如下面的代码,就是接收两个参数,而接收多个参数需要使用 @Param 注解,那么为什么要加该注解呢?这个问题要弄明白就必须来研究 Mybatis 底层对于这些参数是如何处理的。
User select(@Param("username") String username,@Param("password") String password);
<select id="select" resultType="user">
    select *
    from tb_user
    where
        username=#{username}
        and password=#{password}
</select> 
我们在接口方法中定义多个参数, Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param注解时有以下命名规则:
arg 开头 :第一个参数就叫 arg0 ,第二个参数就叫 arg1 ,以此类推。如:

map.put("arg0" ,参数值 1);
map.put("arg1" ,参数值 2);
param 开头 : 第一个参数就叫 param1 ,第二个参数就叫 param2 ,依次类推。如:

map.put("param1" ,参数值 1);
map.put("param2" ,参数值 2);
在映射配合文件的SQL语句中使用用 arg 开头的和 param 书写,代码的可读性会变的特别差,此时可以使用 @Param注解。在接口方法参数上使用 @Param 注解,Mybatis 会将 arg 开头的键名替换为对应注解的属性值。
结论:以后接口参数是多个时,在每个参数上都使用 @Param 注解。这样代码的可读性更高。
1.10.2单个参数
POJO 类型
直接使用。要求 属性名 参数占位符名称 一致
Map 集合类型
直接使用。要求 map集合的键名 参数占位符名称 一致
Collection 集合类型
Mybatis 会将集合封装到 map 集合中,如下:
map.put("arg0" collection 集合 );
map.put("collection" collection 集合 ;
可以使用 @Param 注解替换 map 集合中默认的 arg 键名。
List 集合类型
Mybatis 会将集合封装到 map 集合中,如下:
map.put("arg0" list 集合 );
map.put("collection" list 集合 );
map.put("list" list 集合 );
可以使用 @Param 注解替换 map 集合中默认的 arg 键名。
Array 类型
Mybatis 会将集合封装到 map 集合中,如下:
map.put("arg0" ,数组 );
map.put("array" ,数组 );
可以使用 @Param 注解替换 map 集合中默认的 arg 键名。
其他类型

比如int类型, 参数占位符名称 叫什么都可以。尽量做到见名知意

1.11注解实现CRUD

使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发
@Select(value = "select * from tb_user where id = #{id}") 
public User select(int id);
Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下:
查询 : @Select
添加 : @Insert
修改 : @Update
删除 : @Delete

 总结:注解完成简单功能,配置文件完成复杂功能。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值