• MyBatis快速上手与知识点总结



    阅读提示:

    本文默认已经预装预装maven

    1、MyBatis概述

    1.1 MyBatis概述

    • 持久层框架,用于简化JDBC开发,是对JDBC的封装

      持久层:

      • 负责将数据保存到数据库的代码部分
      • Java EE三层架构:表现层、业务层、持久层

    1.2 JDBC缺点

    • 硬编码,不利于维护
      • 注册驱动、获取连接
      • SQL语句
    • 操作繁琐
      • 手动设置参数
      • 手动封装结果集

    1.3 MyBatis优化

    • 硬编码 --> 配置文件
    • 繁琐惭怍 --> 框架封装自动完成

    2、MyBatis快速入门

    • 需求:查询user表中的所有数据

    • SQL

      create database mybatis;
      use mybatis;
      
      drop table if exists tb_user;
      
      create table tb_user(
      	id int primary key auto_increment,
      	username varchar(20),
      	password varchar(20),
      	gender char(1),
      	addr varchar(30)
      );
      
      INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
      INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
      INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
      
    • 代码实现

      • 创建模块,导入坐标

        在pom.xml中配置文件中添加依赖的坐标

        注意:需要在项目的resources目录下创建logback的配置文件

        <dependencies>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.5version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.46version>
            dependency>
            
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.13version>
                <scope>testscope>
            dependency>
            
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>1.7.20version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-classicartifactId>
                <version>1.2.3version>
            dependency>
            
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>1.2.3version>
            dependency>
        dependencies>
        
      • 编写MyBatis核心文件

        核心文件用于替换信息,解决硬编码问题

        在模块下的resources目录下创建mybatis的配置文件mybatis-config.xml

        
        configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <configuration>
            <environments default="development">
                <environment id="development">
                    
                    <transactionManager type="JDBC"/>
                    
                    <dataSource type="POOLED">
                        <property name="driver" value="com.mysql.jdbc.Driver"/>
                        <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                        <property name="username" value="root"/>
                        <property name="password" value="123456"/>
                    dataSource>
                environment>
            environments>
            
            <mappers>
                <mapper resource="UserMapper.xml"/>
            mappers>
        configuration>
        
      • 编写SQL映射文件

        SQL映射文件用于统一管理SQL语句,解决硬编码问题

        在模块的resources目录下创建映射配置文件UserMaooer.xml

        
        mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
        <mapper namespace="test">
            
            <select id="selectAll" resultType="priv.dandelion.entity.User">
                select * from tb_user;
            select>
        mapper>
        
      • 编码

        • 实体类

          package priv.dandelion.entity;
          
          public class User {
          
              private Integer id;
              private String username;
              private String password;
              private String gender;
              private String address;
          
              public User() {
              }
          
              public User(Integer id, String username, String password, String gender, String address) {
                  this.id = id;
                  this.username = username;
                  this.password = password;
                  this.gender = gender;
                  this.address = address;
              }
          
              public Integer getId() {
                  return id;
              }
          
              public void setId(Integer id) {
                  this.id = id;
              }
          
              public String getUsername() {
                  return username;
              }
          
              public void setUsername(String username) {
                  this.username = username;
              }
          
              public String getPassword() {
                  return password;
              }
          
              public void setPassword(String password) {
                  this.password = password;
              }
          
              public String getGender() {
                  return gender;
              }
          
              public void setGender(String gender) {
                  this.gender = gender;
              }
          
              public String getAddress() {
                  return address;
              }
          
              public void setAddress(String address) {
                  this.address = address;
              }
          
              @Override
              public String toString() {
                  return "User{" +
                          "id=" + id +
                          ", username='" + username + '\'' +
                          ", password='" + password + '\'' +
                          ", gender='" + gender + '\'' +
                          ", address='" + address + '\'' +
                          '}';
              }
          }
          
          
        • 测试类

          public static void main(String[] args) throws IOException {
              // 加载mybatis的核心配置文件,获取SqlSessionFactory
              String resource = "mybatis-config.xml";
              InputStream inputStream = Resources.getResourceAsStream(resource);
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              // 获取Session对象,执行SQL语句
              SqlSession sqlSession = sqlSessionFactory.openSession();
              // 执行SQL,处理结果
              List users = sqlSession.selectList("test.selectAll");
              System.out.println(users);
              // 释放资源
              sqlSession.close();
          }
          

    3、Mapper代理开发

    3.1 Mapper代理开发概述

    解决形如上述测试类中List users = sqlSession.selectList("test.selectAll");的硬编码问题

    • 解决原生方式中的硬编码
    • 简化后期的SQL执行

    3.2 使用Mapper代理要求

    • 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下

      maven项目开发时要求code和resources分开,可在resources中创建相同包文件来是实现上述效果

    • 设置SQL映射文件的namespace属性未Mapper接口的全限定名

    • 在Mapper接口中定义方法,方法名就是SQL映射文件中SQL语句的id,并且参数类型和返回值类型一致

    3.3 案例代码实现

    • 修改SQL映射文件UserMapper.xml

      同时还要修改其路径

      
      mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="priv.dandelion.mapper.UserMapper">
          <select id="selectAll" resultType="priv.dandelion.entity.User">
              select * from tb_user;
          select>
      mapper>
      
    • 创建对应的Mapper接口UserMapper.interface

      public interface UserMapper {
          List selectAll();
      }
      
    • 修改mybatis核心配置文件中加载SQL映射的的路径

      <mappers>
          <mapper resource="priv/dandelion/mapper/UserMapper.xml"/>
      mappers>
      
    • 测试代码

      public static void main(String[] args) throws IOException {
          // 加载mybatis的核心配置文件,获取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          // 获取Session对象,执行SQL语句
          SqlSession sqlSession = sqlSessionFactory.openSession();
          // 执行SQL,处理结果
          // 获取UserMapper接口的代理对象
          UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
          List users = userMapper.selectAll();
          System.out.println(users);
          // 释放资源
          sqlSession.close();
      }
      
    • 改进

      如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载,简化mybatis核心配置文件

      <mappers>
          
          
          
          <package name="priv.dandelion.mapper"/>
      mappers>
      

    4、核心配置文件

    4.1 多环境配置

    在核心配置文件的 environments 标签中其实是可以配置多个 environment ,使用 id 给每段环境起名,在 environments 中使用 default='环境id' 来指定使用哪儿段配置。我们一般就配置一个 environment 即可

    
    configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <typeAliases>
            <package name="priv.dandelion.entity"/>
        typeAliases>
    
        <environments default="development">
            <environment id="development">
                
                <transactionManager type="JDBC"/>
                
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    
                    <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
    
            <environment id="test">
                <transactionManager type="JDBC"/>
                
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
        
        <mappers>
            
            <package name="priv.dandelion.mapper"/>
        mappers>
    configuration>
    

    4.2 类型别名

    映射配置文件中的resultType属性需要配置数据封装的类型(类的全限定名),繁琐

    Mybatis 提供了 类型别名(typeAliases) 可以简化这部分的书写

    <configuration>
        
        <typeAliases>
            <package name="priv.dandelion.entity"/>
        typeAliases>
    configuration>
    
    <mapper namespace="priv.dandelion.mapper.UserMapper">
        
        <select id="selectAll" resultType="user">
            select * from tb_user;
        select>
    mapper>
    

    5、配置文件实现CRUD

    5.1 环境准备

    • SQL

      -- 删除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;
      
    • 实体类

      public class Brand {
          
          private Integer id;
          private String brand_name;
          private String company_name;
          private Integer ordered;
          private String description;
          private Integer status;
      
          public Brand() {
          }
      
          public Brand(
                  Integer id,
                  String brand_name,
                  String company_name,
                  Integer ordered,
                  String description,
                  Integer status
          ) {
              this.id = id;
              this.brand_name = brand_name;
              this.company_name = company_name;
              this.ordered = ordered;
              this.description = description;
              this.status = status;
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getBrand_name() {
              return brand_name;
          }
      
          public void setBrand_name(String brand_name) {
              this.brand_name = brand_name;
          }
      
          public String getCompany_name() {
              return company_name;
          }
      
          public void setCompany_name(String company_name) {
              this.company_name = company_name;
          }
      
          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 +
                      ", brand_name='" + brand_name + '\'' +
                      ", company_name='" + company_name + '\'' +
                      ", ordered=" + ordered +
                      ", description='" + description + '\'' +
                      ", status=" + status +
                      '}';
          }
      }
      
    • 安装插件MyBatisX

    • 步骤

      1. 编写接口方法Mapper接口
        • 参数
        • 返回值
      2. 在SQL映射文件中编写SQL语句
        • MyBatisX插件自动补全
        • 编写SQL
        • 若数据库字段名和实体类字段名不同,则需要解决该问题(见 5.2 SQL映射文件)
      3. 编写执行测试
        • 获取SqlSessionFactory
        • 获取sqlSession对象
        • 获取mapper接口的代理对象
        • 执行方法
        • 释放资源

    5.2 查询所有数据

    本节要点:

    1. 测试类的编写方式
    2. 解决数据库字段和实体类字段名不同的问题
    • 编写接口方法

      public interface BrandMapper {
          public List selectAll();
      }
      
    • 编写SQL映射文件

      
      mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="priv.dandelion.mapper.BrandMapper">
      
      
      
          
          <resultMap id="brandResultMap" type="brand">
              <result column="brand_name" property="brandName" />
              <result column="company_name" property="companyName" />
          resultMap>
      
          
          <select id="selectAll" resultMap="brandResultMap">
              select *
              from tb_brand;
          select>
      
      mapper>
      
    • 编写测试方法

      @Test
      public void testSelectAll() throws IOException {
          // 获取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
          // 获取sqlSession对象
          SqlSession sqlSession = sqlSessionFactory.openSession();
      
          // 获取mapper接口的代理对象
          BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
          // 执行方法
          List brands = brandMapper.selectAll();
          System.out.println(brands);
      
          // 释放资源
          sqlSession.close();
      }
      

    5.3 查询

    本节要点:

    1. MyBatis的SQL映射文件中,SQL语句如何接收对应参数
    • 使用占位符进行参数传递

      • 占位符名称和参数保持一致

      • 占位符

        • #{占位符名}:会替换为?防止SQL注入,一般用于替换字段值
        • ${占位符名}:存在SQL注入问题,一般用于执行动态SQL语句,如表名列名不固定的情况(见)
    • 编写接口方法

      void update(Brand brand);
      
    • SQL映射文件查询代码标签

      <resultMap id="brandResultMap" type="brand">
          <result column="brand_name" property="brandName" />
          <result column="company_name" property="companyName" />
      resultMap>
      <select id="selectById" resultMap="brandResultMap">
          select *
          from tb_brand where id = #{id};
      select>
      
    • 测试方法

      @Test
          public void testSelectByCondition() throws IOException {
              // 接收参数
              int status = 1;
              String companyName = "华为";
              String brandName = "华为";
      
              // 获取SqlSessionFactory
              String resource = "mybatis-config.xml";
              InputStream inputStream = Resources.getResourceAsStream(resource);
              SqlSessionFactory sqlSessionFactory = 
                  new SqlSessionFactoryBuilder().build(inputStream);
      
              // 获取sqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
      
              // 获取mapper接口的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
              // 执行方法
              companyName = "%" + companyName + "%";
              brandName = "%" + brandName + "%";
              List brands = brandMapper.selectByCondition(status, companyName, brandName);
              System.out.println(brands);
      
              // 释放资源
              sqlSession.close();
          }
      

    5.4 多条件查询

    本节要点:

    1. 多条件查询:如果有多个参数,需要使用@Paran("SQL参数占位符名称")注解
    2. 多条件的动态条件查询:对象属性名称要和参数占位符名称一致
      (详见5-2解决数据库字段和实体类字段名不同的问题)
    3. 单条件的动态条件查询:保证key要和参数占位符名称一致
    • 多条件查询

      • SQL映射文件

        
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        resultMap>
        
        
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
            where status = #{status}
            and company_name like #{companyName}
            and brand_name like #{brandName}
        select>
        
      • 散装参数

        • 接口

          // 散装参数
          List selectByCondition(
              @Param("status")int status, 
              @Param("companyName")String companyName, 
              @Param("brandName")String brandName
          );
          
        • 测试方法

          @Test
              public void testSelectByCondition() throws IOException {
                  // 接收参数
                  int status = 1;
                  String companyName = "华为";
                  String brandName = "华为";
          
                  // 获取SqlSessionFactory
                  String resource = "mybatis-config.xml";
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  SqlSessionFactory sqlSessionFactory =
                      new SqlSessionFactoryBuilder().build(inputStream);
          
                  // 获取sqlSession对象
                  SqlSession sqlSession = sqlSessionFactory.openSession();
          
                  // 获取mapper接口的代理对象
                  BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
          
                  // 执行方法
                  companyName = "%" + companyName + "%";
                  brandName = "%" + brandName + "%";
                  List brands = brandMapper.selectByCondition(
                      status, companyName, brandName);
                  System.out.println(brands);
          
                  // 释放资源
                  sqlSession.close();
              }
          
      • 对象参数

        • 接口

          // 对象参数
          List selectByCondition(Brand brand);
          
        • 测试方法

          // 细节不表,仅展示执行方法
          // 执行方法
          Brand brand = new Brand();
          brand.setStatus(status);
          brand.setCompanyName("%" + companyName + "%");
          brand.setBrandName("%" + brandName + "%");
          List brands = brandMapper.selectByCondition(brand);
          System.out.println(brands);
          
      • map集合参数

        • 接口

          // 集合参数
          List selectByCondition(Map map);
          
        • 测试方法

          // 细节不表,仅展示执行方法
          // 执行方法
          Map map = new HashMap();
          map.put("status", status);
          map.put("companyName", "%" + companyName + "%");
          map.put("brandName", "%" + brandName + "%");
          List brands = brandMapper.selectByCondition(map);
          System.out.println(brands);
          
    • 多条件动态条件查询

      优化条件查询,如页面上表单存在多个条件选项,但实际填写表单仅使用部分条件筛选的情况

      • SQL映射文件

        
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        resultMap>
        
        
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
            <where>
                <if test="status != null">
                    status = #{status}
                if>
                <if test="companyName != null">
                    and company_name like #{companyName}
                if>
                <if test="brandName != null">
                    and brand_name like #{brandName}
                if>
            where>
        select>
        

        注:

        1. if标签的test属性中可以包含逻辑或等逻辑判断,使用andor进行连接

        2. 若条件SQL中同时包含AND等连接符

          • 对所有的条件前都加AND,并在WHERE后加任意真判断,即WHERE 1=1 AND ... AND ...
          • 加入判断标签造轮子,自行决定添加AND的条件
          • 使用标签替换原SQL中的WHERE关键字,MyBatis将自动进行语法修正,如示例所示
    • 单条件的动态条件查询

      优化条件查询:如表单中存在多个条件筛选,但仅有其中一个生效的情况

      • 使用标签
        • choose标签类似于Java中的switch
        • when标签类似于Java中的case
        • otherwise标签类似于Java中的default
      • SQL映射文件

        
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName"/>
            <result column="company_name" property="companyName"/>
        resultMap>
        
        
        <select id="selectByConditionSingle" resultMap="brandResultMap">
            select *
            from tb_brand
            <where>
                <choose>
                    <when test="status != null">
                        status = #{status}
                    when>
                    <when test="companyName != null and companyName != ''">
                        company_name like #{companyName}
                    when>
                    <when test="brandName != null and brandName != ''">
                        brand_name like #{brandName}
                    when>
                choose>
            where>
        select>
        

    5.6 添加数据与MyBatis事务

    • 添加

      • 接口

        // 添加
        void add(Brand brand);
        
      • SQL映射文件

        <insert id="add">
            insert into tb_brand (brand_name, company_name, ordered, description, status)
            values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
        insert>
        
      • 测试方法

        @Test
        public void testAdd() throws IOException {
            // 接收参数
            int status = 1;
            String companyName = "aaa";
            String brandName = "xxx";
            String description = "这是一段介绍";
            int ordered = 100;
        
            // 获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(inputStream);
        
            // 获取sqlSession对象
            // SqlSession sqlSession = sqlSessionFactory.openSession();
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
        
            // 获取mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        
            // 执行方法
            Brand brand = new Brand();
            brand.setStatus(1);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
            brandMapper.add(brand);
            System.out.println("添加成功");
        
            // 提交事务
            // sqlSession.commit();
        
            // 释放资源
            sqlSession.close();
        }
        
    • Mybatis事务

      MyBatis默认手动事务,执行添加等操作时会自动回滚

      • MyBayis事务处理的方法

        // 方法一:在获取sqlSession对象时设置参数,开启自动事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        sqlSession.close();
        // 方法二:手动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.commit();
        sqlSession.close();
        
    • 添加 - 主键返回

      传入实体类对象进行数据添加,在数据添加完成后,会将id信息写回该实体类对象

      • SQL映射文件

        <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>
        
      • 获取写回信息

        Integer id = brand.getId();
        

    5.7 修改

    • 修改整条数据

      • 接口

        // 修改,可使用int返回值,返回受影响行数
        void update(Brand brand);
        
      • SQL映射文件

        <update id="update">
            update tb_brand
            set brand_name = #{brandName},
            set company_name = #{companyName},
            set ordered = #{ordered},
            set description = #{description},
            set status = #{status}
            where id = #{id};
        update>
        
    • 修改部分字段

      优化上述代码应对仅修改部分属性导致其他属性数据丢失问题

      使用标签替换set关键字列表,区别于标签,注意语法

      • SQL映射文件

        <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>
        
      • 测试代码

        @Test
        public void testUpdate() throws IOException {
            // 接收参数
            int id = 5;
            int status = 0;
            String companyName = "AAA";
            String brandName = "XXX";
            int ordered = 300;
        
            // 获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(inputStream);
        
            // 获取sqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
        
            // 获取mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        
            // 执行方法
            Brand brand = new Brand();
            brand.setId(id);
            brand.setStatus(status);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setOrdered(ordered);
            brandMapper.update(brand);
            System.out.println("修改成功");
        
            // 释放资源
            sqlSession.close();
        }
        

    5.8 删除数据

    • 删除一条数据

      • 接口

        // 删除一条数据
        void deleteById(int id);
        
      • SQL映射文件

        <delete id="deleteById">
            delete
            from tb_brand
            where id = #{id};
        delete>
        
      • 测试

        @Test
        public void testDeleteById() throws IOException {
            // 接收参数
            int id = 5;
        
            // 获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(inputStream);
        
            // 获取sqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
        
            // 获取mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        
            // 执行方法
            brandMapper.deleteById(id);
            System.out.println("删除成功");
        
            // 释放资源
            sqlSession.close();
        }
        
    • 批量删除数据

      用于解决删除时传入参数为数组的情况

      • 使用标签代替SQL语句中的id in (?, ?, ..., ?)
        • collection属性为MyBatis封装后数组对应的key,封装后属性值应为array(见注释)
          • MyBatis默认会将数组参数封装为Map集合,其keyarray,即 array = ids
          • 可在接口中对参数数组使用@Param注解,将封装后的key手动命名,则可在映射文件中使用
        • separator属性为分隔符
        • openclose属性分别为在前后拼接字符,主要用于代码规范,示例中未展示
      • 接口

        // 删除多个数据
        void deleteByIds(@Param("ids")int[] ids);
        
      • SQL映射文件

        <delete id="deleteByIds">
            delete
            from tb_brand
            where id
            in (
            
            <foreach collection="ids" item="id" separator=",">
                #{id}
            foreach>
            );
        delete>
        
      • 测试

        @Test
        public void testDeleteByIds() throws IOException {
            // 接收参数
            int[] ids = {6, 7};
        
            // 获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(inputStream);
        
            // 获取sqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
        
            // 获取mapper接口的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        
            // 执行方法
            brandMapper.deleteByIds(ids);
            System.out.println("删除成功");
        
            // 释放资源
            sqlSession.close();
        }
        

    5.9 MyBatis参数传递

    • 概述

    • 多个参数

      设有如下代码:

      User select(@Param("username") String username,@Param("password") String password);
      

      MyBatis会将散装的多个参数封装为Map集合

      • 若不使用@Param注解,则会使用以下命名规则:

        map.put("arg0",参数值1);
        map.put("arg1",参数值2);
        map.put("param1",参数值1);
        map.put("param2",参数值2);
        

        即Map集合中的参数的key分别为arg0, arg1, param1, param2

      • 使用@Param注解会将Map集合中的参数的arg替换为指定内容,增强其可读性

    • 单个参数

      • POJO类型:直接使用,要求属性名和参数占位符名称一致(见 5.2 SQL映射文件)

      • Map集合类型:直接使用,要求key和参数占位符名称一致(见 5.2 SQL映射文件)

      • Collection集合类型:封装Map集合,可以使用@Param注解替换Map集合中默认arg键名

        map.put("arg0",collection集合);
        map.put("collection",collection集合;
        
      • List集合类型:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

        map.put("arg0",list集合);
        map.put("collection",list集合);
        map.put("list",list集合);
        
      • Array类型:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名

        map.put("arg0",数组);
        map.put("array",数组);
        
      • 其他类型:直接使用,与参数占位符无关,但尽量见名知意

    6、通过注解实现CRUD

    • 概述

      • 用于简化开发,可以对简单的查询使用注解进行操作,以替换xml中的statement
      • 对于复杂的查询,仍然建议使用xml配置文件,否则代码会十分混乱
    • 使用方法

      • 注解(部分)

        • 查询 :@Select
        • 添加 :@Insert
        • 修改 :@Update
        • 删除 :@Delete
      • 示例

        • 使用注解简化查询

          • 原接口

            Brand selectById(int id);
            
          • 原SQL映射文件

            
            <resultMap id="brandResultMap" type="brand">
                <result column="brand_name" property="brandName"/>
                <result column="company_name" property="companyName"/>
            resultMap>
            
            <select id="selectById" resultMap="brandResultMap">
                select *
                from tb_brand
                where id = #{id};
            select>
            
          • 使用注解进行开发

            • 接口

              @ResultMap("brandResultMap")		// 解决数据库和实体类字段名称不同
              @Select("select * from tb_brand where id = #{id}")	// 查询语句
              Brand selectById(int id);
              
            • SQL映射文件:不再需要原先的statement

              
              <resultMap id="brandResultMap" type="brand">
                  <result column="brand_name" property="brandName"/>
                  <result column="company_name" property="companyName"/>
              resultMap>
              
              
              
  • 相关阅读:
    3396: [Usaco2009 Jan]Total flow 水流 (最大流)
    Vue脚手架Ⅰ(初始化脚手架,render函数,修改默认配置,ref属性)
    nvm安装与使用
    MybatisPlus多数据源
    深入学习与探索:高级数据结构与复杂算法
    STM32(15)USART编程
    为啥要用C艹不用C?
    【数据聚类】基于蝙蝠算法实现数据聚类附matlab代码
    说说C++的默认构造函数
    快上车,LLM专列:想要的资源统统给你准备好了
  • 原文地址:https://www.cnblogs.com/dandelion-000-blog/p/16636393.html