大数据------JavaWeb------MyBatis(完整知识点汇总)

MyBatis

MyBatis简介

  • 定义

    • 它是一款优秀的持久层框架,用于简化JDBC开发
    • 它原来是Apache的一个开源项目iBatis,后来改名为MyBatis
    • 中文官网:https://mybatis.org/mybatis-3/zh_CN/index.html
  • JaveEE三层架构

    • 表现层(做页面展示)
    • 业务层(做逻辑处理)
    • 持久层(负责将数据保存到数据库的那一层代码。即做数据持久化的)
  • 框架

    • 框架是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
    • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
  • JDBC缺点

    • 硬编码
      • 将一些字符串信息写到代码中,且这些字符串信息后续可能会有所改变,比如:注册驱动和获取连接的部分
    • 操作繁琐
      • 手动设置参数:比如利用PreparedStatement类中的public void setXxx(参数1,参数2)方法来对SQL语句中的?进行赋值时,若?较多,则需要调用多次该方法,这样就比较繁琐
      • 手动封装ResultSet结果集:封装结果集时需要将结果集中需要的数据拿出来然后放到对象中,最后将对象放到集合中,比较繁琐

    MyBatis可将造成硬编码部分的代码写到配置文件中;将操作繁琐部分的代码简化,如下图所示

    在这里插入图片描述

  • MyBatis优点

    • 是一款优秀的持久层框架
    • 支持自定义 SQL、存储过程以及高级映射
    • 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作
    • 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  • MyBatis两种版本

    • 普通版------MyBatis
    • 增强版------MyBatis-Plus

MyBatis环境搭建

MyBatis快速入门(可跟着MyBatis官网的入门来操作)

示例:查询user表中所有的数据

  • 步骤

    • 第一步:创建mybatis数据库并在该数据库中创建tb_user表,添加数据.

      #创建数据库
      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)L,
        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', '男', '西安');
      

      在这里插入图片描述

    • 第二步:创建模块(该模块是Maven的项目),导入坐标

      • 创建MyBatis的Maven模块

        在这里插入图片描述

      • 导入坐标:从官网的入门中可看到将图示以来写到pom.xml文件中即可,其中x.x.x为MyBatis的版本号。MyBatis导入后也要导入MySQL的坐标依赖以及其它多个需要用到的相关依赖(依赖导入方法可详见Maven部分),具体代码详见下述

        在这里插入图片描述

            <dependencies>
                <!--MyBatis依赖-->
                <dependency>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                    <version>3.5.16</version>
                </dependency>
                
                <!--mysql驱动-->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.33</version>
                </dependency>
        
                <!--Junit单元测试-->
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.13.2</version>
                    <scope>test</scope>
                </dependency>
        
                <!--添加slf4j日志api-->
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                    <version>2.0.12</version>
                </dependency>
        
                <!--添加logback-classic依赖-->
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                    <version>1.5.6</version>
                    <scope>test</scope>
                </dependency>
                
                <!--添加logback-core依赖-->
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.4.14</version>
                </dependency>
            </dependencies>
        
    • 第三步:编写SQL映射文件(统一管理sql语句,解决JDBC的硬编码问题)

      • 写sql映射文件(对应官网 探究已映射的 SQL 语句 ):在该Maven项目的源代码配置文件目录(即main包下的resources目录下)创建一个userMapper.xml文件,然后将官网的简单示例代码复制到该文件中进行对应修改,该文件代码简单示例如下

        sql映射文件命名规范tableNameMapper.xml即要操作的表名后加上Mapper,比如我现在要用该映射文件操作stu表,则sql映射文件名为stuMapper.xml

        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
        <!--
            namespace:名称空间
        -->
        <mapper namespace="test">
            <!--
                id:为sql语句的唯一标识
                resultType:为对应sql语句执行完毕后返回结果的类型
                    假设我要将其执行的结果封装到一个类中则此时该属性后的值就应该为全类名
                    由于我现在是对user表进行操作的,所以我就将执行结果保存到一个user类中
                    所以就需要先在Maven项目的源代码java文件目录(即main包下的java目录下)创建一个user类,该类中的属性和方法随后再写即可,此处先创建出来是为了让resultType有属性值
                    然后resultType="at.guigu.pojo.User"
            -->
            <select id="selectAll" resultType="at.guigu.pojo.User">
                select * from tb_user;
            </select>
        </mapper>
        

        注意:

        ​ 若要将sql语句的查询结果封装成一个对象则该数据封装的对象一般放在名为pojo的包中

        ​ 若嫌弃resultType的属性值太长造成冗余,可为其设置别名

        在这里插入图片描述

    • 第四步:编写MyBatis核心配置文件(替换连接信息,解决JDBC的硬编码问题)

      • 从官网的入门中可看到将依赖导入到pom.xml文件后需要构建SqlSessionFactory(可在XML中构建,也可不使用XML构建)

        在这里插入图片描述

      • 在XML中构建SqlSessionFactory的步骤如下:

        1. 在该Maven项目的源代码配置文件目录(即main包下的resources目录下)创建一个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>
              <environments default="development">
                  <environment id="development">
                      <transactionManager type="JDBC"/>
                      <dataSource type="POOLED">
                          <!--数据库 连接信息-->
                          <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                          <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                          <property name="username" value="root"/>
                          <property name="password" value="123456"/>
                      </dataSource>
                  </environment>
              </environments>
              <mappers>
                  <!--加载SQL映射文件:传入sql映射文件的路径-->
                  <mapper resource="UserMapper.xml"/>
              </mappers>
          </configuration>
          

          由于mybatis-config.xml文件和UserMapper.xml文件均在一个目录下,属于同一级,所以在传入sql映射文件路径时直接写入该文件名即可

    • 第五步:编码

      • 定义POJO类(对于数据封装的对象一般放在名为pojo的包中)

        在刚刚创建的实体类User类中写入自己想要的sql语句执行后的结果的属性及方法

        package at.guigu.pojo;
        
        public class User {
            private int id;
            private String username;
            private String password;
            private String gender;
            private String addr;
        
            public User() {
            }
        
            public User(int id, String username, String password, String gender, String addr) {
                this.id = id;
                this.username = username;
                this.password = password;
                this.gender = gender;
                this.addr = addr;
            }
        
            public int getId() {
                return id;
            }
        
            public void setId(int 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 getAddr() {
                return addr;
            }
        
            public void setAddr(String addr) {
                this.addr = addr;
            }
        
            @Override
            public String toString() {
                return "User{" +
                        "id=" + id +
                        ", username='" + username + '\'' +
                        ", password='" + password + '\'' +
                        ", gender='" + gender + '\'' +
                        ", addr='" + addr + '\'' +
                        '}';
            }
        }
        
      • 源代码java文件目录创建类:加载核心配置文件,获取SqlSessionFactory对象;然后获取SqlSession对象,执行SQL语句;随后释放资源

        • 类中来加载MyBatis核心配置文件并获取SqlSessionFactory对象,获取该对象代码如下(直接从官网复制即可,不需记忆):

          //配置mybatis-config.xml文件路径
          String resource = "org/mybatis/example/mybatis-config.xml";
          //利用Resources类中的静态方法将配置文件加载到内存
          InputStream inputStream = Resources.getResourceAsStream(resource);
          获取SqlSessionFactory对象
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
          
        • 获取SqlSession对象,执行SQL语句,使用的接口、类及方法如下

          SqlSessionFactory接口的方法解释
          SqlSession openSession()获取SqlSession对象
          SqlSession接口的方法解释
          <E> List<E> selectList(String statement)执行sql语句。参数为namespace.id

        代码如下:

        package at.guigu;
        
        import at.guigu.pojo.User;
        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;
        import java.io.InputStream;
        import java.util.List;
        
        public class MyBatisDemoOne {
            public static void main(String[] args) throws Exception {
                //1 加载核心配置文件,获取`SqlSessionFactory`对象
                //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
                String resource = "mybatis-config.xml";
                //1.2 利用Resources类中的静态方法将配置文件加载到内存
                InputStream inputStream = Resources.getResourceAsStream(resource);
                //1.3 获取SqlSessionFactory对象
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        
                //2 获取SqlSession对象,执行SQL语句
                //2.1 获取SqlSession对象
                SqlSession sqlSession = sqlSessionFactory.openSession();
                //2.2 执行sql语句
                List<User> users = sqlSession.selectList("test.selectAll");
                System.out.println(users);
            }
        }
        

        注意 :在该代码中,<E> List<E> selectList(String statement)方法的参数仍会造成硬编码问题,因为不同的sql语句有不同的namespace和id,为解决该问题,可详见Mapper代理开发部分

问题解决

SQL映射文件的标红警告提示

在这里插入图片描述

  • 产生原因

    • idea和数据库未建立连接,导致idea不能识别表信息从而标红
  • 解决方法:在idea中配置mysql数据库连接信息

    • 按图示操作即可

      在这里插入图片描述

      在这里插入图片描述

      在这里插入图片描述

  • 该方法不仅是SQL映射文件的标红警告提示的方法,还是可以在idea中直接操作数据库的方法

    • idea与数据库连接后可在idea中新建写sql语句的console面板来操作数据库,如图所示

      在这里插入图片描述

      idea中写sql语句时很强大,自动提示和补全比较牛

Mapper代理开发

在这里插入图片描述

  • 作用

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

    在这里插入图片描述

  • Mapper代理开发步骤及要求

    • 第一步:定义与SQL映射文件同名的Mapper接口(Maven项目中接口统一在一个包中,此处假设mapper包中写接口类),并且将Mapper接口和SQL映射文件放置在同一个目录下

      • 定义与SQL映射文件同名的Mapper接口:由于博主的sql映射文件名为UserMapper.xml,所以接口名为UserMapper

      • 将Mapper接口和SQL映射文件放置在同一个目录下:在该Maven项目的源代码配置文件目录(即main包下的resources目录下)创建多层目录,多层目录对应Mapper接口所在的多层包,比如我的UserMapper接口在at.guigu.mapper包下,则此时就在resources目录下创建多层目录格式为at/guigu/mapper,然后将sql映射文件UserMapper.xml拖入到该mapper目录下

        在这里插入图片描述

      • 右键UserMapper.xmlSQL映射文件→Copy Path/ReferencePath From Source Root,复制UserMapper.xmlSQL映射文件现在的路径,然后更改mybatis-config.xmlMyBatis核心配置文件中sql映射文件的路径即可。

    • 第二步:设置SQL映射文件UserMapper.xml的namespace属性为Mapper接口的全限定名,修改后的代码如下所示

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--
          namespace:名称空间
      -->
      <mapper namespace="at.guigu.mapper.UserMapper">
          <!--
              id:为sql语句的唯一标识
              resultType:为对应sql语句执行完毕后返回结果的类型
                  假设我要将其执行的结果封装到一个类中则此时该属性后的值即为全类名
                  由于我现在是对user表进行操作的,所以我就将执行结果保存到一个user类中
                  所以就需要先在Maven项目的源代码java文件目录(即main包下的java目录下)创建一个user类
                  然后resultType="at.guigu.pojo.User"
          -->
          <select id="selectAll" resultType="at.guigu.pojo.User">
              select * from tb_user;
          </select>
      </mapper>
      
    • 第三步:在Mapper接口UserMapper中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

      • 由SQL映射文件可知,方法名为selectAll,返回值类型为User。然后判断对应的sql语句的返回结果是一个结果还是多个结果,若是一个则在接口中定义一个对象即可;若是多个则需定义集合,将来执行sql语句后的结果就会直接放在集合中

      在这里插入图片描述

    • 第四步:编码

      • 通过SqlSession的getMapper方法获取Mapper接口的代理对象
      • 调用对应方法完成sql语句的执行
    • 第三四步代码如下

      package at.guigu.pojo;
      
      import at.guigu.mapper.UserMapper;
      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;
      import java.io.InputStream;
      import java.util.List;
      
      //MyBatis代理开发
      public class MyBatisDemoTwo {
          public static void main(String[] args) throws IOException {
              //1 加载核心配置文件,获取`SqlSessionFactory`对象
              //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
              String resource = "mybatis-config.xml";
              //1.2 利用Resources类中的静态方法将配置文件加载到内存
              InputStream inputStream = Resources.getResourceAsStream(resource);
              //1.3 获取SqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
              //2.3 执行sql语句
              List<User> users = userMapper.selectAll();
      
              System.out.println(users);
          }
      }
      

      在这里插入图片描述

  • 注意:若Mapper接口名称和SQL映射文件名称相同并且在同一目录下则可使用包扫描的方式简化SQL映射文件的加载

    • 由Mapper代理开发的要求可知,SQL映射文件的名称与对应Mapper接口的名称一定相同且Mapper接口与对应的SQL映射文件均在同一个目录下

      • 此处在同一个目录下是近似看作在同一个目录下,以博主的项目代码为例:UserMapper接口在java目录下的at.guigu.mapper包下,而对应的SQL映射文件在resources目录下的at.guigu.mapper目录下,由于目录结构相同,所以可近似看作在同一个目录下。此时MyBatis核心配置文件中sql映射文件的路径,就可写为如下形式:
      <mappers>
          <!--加载SQL映射文件-->
          <!--
      	<mapper resource="at/guigu/mapper2/UserMapper.xml">
      	-->
      	<package name="at.guigu.mapper"/>
      </mappers>
      
    • 优点:以后项目大的话就会有多个SQL映射文件,原来的方式(即<mapper resource="at/guigu/mapper2/UserMapper.xml">)只是一次加载一个映射文件,而现在的新方式(即<package name="at.guigu.mapper"/>)是加载该目录下的所有映射文件,不需要重复使用<mapper resource="SQL映射文件路径">来加载SQL映射文件

MyBatis核心配置文件(mybatis-config.xml)

  • 该核心配置文件中可进行的配置内容详见官网中的XML配置

    在这里插入图片描述

  • 部分标签解释如下(其它标签可详见官网)

    标签解释
    typeAliases设置包下单个类的类型别名或设置包下所有类的类型别名
    environments配置数据库连接环境信息,可配置多个environment,并通过default属性来切换不同的environment
    mappers定义 SQL 映射文件

设置别名

在MyBatis核心配置文件中设置别名(即mybatis-config.xml)

假设我在at.guigu.pojo包下由有多个实体类,实体类的全类名如下:

at.guigu.pojo.Author
at.guigu.pojo.Blog
at.guigu.pojo.Comment
at.guigu.pojo.Post
at.guigu.pojo.Section
at.guigu.pojo.Tag
  • 给单个类的全类名设置类型别名方式一

    <typeAliases>
      <typeAlias alias="Author" type="at.guigu.pojo.Author"/>
      <typeAlias alias="Blog" type="at.guigu.pojo.Blog"/>
      <typeAlias alias="Comment" type="at.guigu.pojo.Comment"/>
      <typeAlias alias="Post" type="at.guigu.pojo.Post"/>
      <typeAlias alias="Section" type="at.guigu.pojo.Section"/>
      <typeAlias alias="Tag" type="at.guigu.pojo.Tag"/>
    </typeAliases>
    
    • 设置完成后在SQL映射文件中定义resultType属性的属性值时即可不用写类的全类名,写其别名即可

      <select id="selectById" resultType="Author"></select>
      <select id="selectById" resultType="Blog"></select>
      <select id="selectById" resultType="Comment"></select>
      <select id="selectById" resultType="Post"></select>
      <select id="selectById" resultType="Section"></select>
      <select id="selectById" resultType="Tag"></select>
      
    • 博主自己的示例图如下

      在这里插入图片描述

  • 给单个类的全类名设置类型别名方式二:利用@Alias("别名")注解为类的全类名设置类型别名

    • 博主自己的示例图如下

    在这里插入图片描述

  • 给包下的所有类的全类名设置类型别名

    <typeAliases>
      <package name="at.guigu.pojo"/>
    </typeAliases>
    
    • 此时相当于给at.guigu.pojo包下的所有类设置类型别名,该包下所有类的类型别名为对应类的首字母小写的类名,比如

      Author的类型别名为author
      Blog的类型别名为blog
      Comment的类型别名为comment
      Post的类型别名为post
      Section的类型别名为section
      Tag的类型别名为tag
      
    • 博主自己的示例图如下

      在这里插入图片描述

  • 注意

    • typeAliases标签在MyBatis核心配置文件中的顺序必须按照官网的顶层结构来写,写在environments标签之前
    • 若在MyBatis的核心配置文件中给某个类设置了别名后又利用注解给该类设置了别名,则会以注解设置的别名为准

MyBatis参数传递注意形式

在这里插入图片描述

  • MyBatis接口的方法可接收各种参数,它的底层会对不同的参数进行不同的封装处理(MyBatis底层提供了一个类ParamNameResolver来封装参数),参数总体有两类
    • 单个参数
      • POJO类型:将sql语句的查询结果封装成一个对象则该数据封装的对象一般放在名为pojo的包中。
      • Map集合、Collection集合、List集合、Array数组、其他类型(即基本数据类型或String类型等)
    • 多个参数
      • 多个参数时要利用注解@Param("参数")来将对应的方法参数放到SQL映射文件中SQL语句对应的参数占位符
  • 需要加@Param("参数")注解的有
    • 单个参数
      • Collection集合、List集合、Array(数组):它们几个都会被封装到Map集合中
    • 多个参数

MyBatis注解开发

  • 特点:

    • 传统的MyBatis是将SQL语句写在SQL映射文件中,而MyBatis注解开发是将SQL语句写在注解中

    • 使用注解开发要比使用配置文件开发更方便

    • 注解直接在对应接口的方法上,如图所示

      在这里插入图片描述

  • 用到的注解

    注解解释
    @Select选择数据
    @Insert插入数据
    @Update修改或更新表中数据
    @Delete删除表中数据
  • 注意

    • 注解是适用于简单的SQL语句,若要做一些复杂的SQL语句则最好使用XML映射
    • 即注解完成简单功能,配置文件完成复杂功能

MyBatis案例

在这里插入图片描述

  • 示例:完成品牌数据的增删改查操作
  • 要完成的功能列表清单
    • 查询
      • 查询所有数据
      • 查看详情
      • 条件查询
    • 添加
    • 修改
      • 修改全部字段
      • 修改动态字段
    • 删除
      • 删除一个
      • 批量删除

环境准备

  • 在mybatis数据库中创建数据库表tb_brand

    DROP TABLE IF EXISTS tb_brand;
    
    -- 创建品牌表brand
    CREATE TABLE IF NOT EXISTS 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;
    
  • 创建实体类Brand------若要将sql语句的查询结果封装成一个对象则该数据封装的对象一般放在名为pojo的包中

    package at.guigu.pojo;
    
    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 Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
            this.id = id;
            this.brandName = brandName;
            this.companyName = companyName;
            this.ordered = ordered;
            this.description = description;
            this.status = 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 +
                    '}';
        }
    }
    
  • 测试用例------写在测试代码java文件目录(即Maven项目的test目录下的java目录下)

    在这里插入图片描述

  • 安装MyBatisX插件

    在这里插入图片描述

    • 它是一款基于IDEA的快速开发插件,为效率而生

    • 功能

      • XML和接口方法互相跳转

        • 安装完成后如图所示,接口中的方法及SQL映射文件中会对应出现小鸟,单击小鸟可实现XML和接口中方法的自动跳转

          在这里插入图片描述

      • 根据接口方法生成statement(即SQL语句)

        • 若接口中新写一个方法,该方法在SQL映射文件中并未定义SQL语句,则此时可借助该插件实现自动生成statement(即SQL语句),如下图所示

        在这里插入图片描述

        在这里插入图片描述

        在这里插入图片描述

实现功能列表清单

查询

查询所有数据
  • 代码略详见快速入门

  • 问题: 由于封装数据的类中属性名和数据库中表的字段名不一致(如图一)可能会造成最终结果显示不出来(如图二)

    即数据库表的字段名称和实体类的属性名称不一样则不能自动封装数据

    在这里插入图片描述

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • 解决方式一: 在SQL映射文件中对SQL语句中的字段名称起别名(即将数据库表中的字段名称的别名设置为与实体类的属性名称对应一样),如下代码所示

      • 该方法有个缺点:即每次查询都需要设置别名,所以详见解决方式二
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--    <select id="selectAll" resultType="at.guigu.pojo.User">-->
          <select id="selectAll" resultType="brand">
      <!--        select * from tb_brand;  改为如下形式-->
              select id, brand_name brandName, company_name companyName, ordered, description, status
              from tb_brand;
          </select>
          <!--    <select id="selectById" resultType="at.guigu.pojo.User">-->
          <select id="selectById" resultType="brand">
              select * from tb_brand where id = #{id};
          </select>
      
      </mapper>
      
    • 解决方式二: 在SQL映射文件中定义SQL片段并引用SQL片段

      • 该方法缺点:不灵活,若SQL片段中是所有的字段名,此时假如只需要查询若干个字段名怎么办
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--定义SQL片段-->
          <sql id = "brand_column">id, brand_name brandName, company_name companyName, ordered, description, status</sql>
          <select id="selectAll" resultType="brand">
      		<!--引入SQL片段-->
              select <include refid="brand_column" />
              from tb_brand;
          </select>
          <!--    <select id="selectById" resultType="at.guigu.pojo.User">-->
          <select id="selectById" resultType="brand">
              select * from tb_brand where id = #{id};
          </select>
      </mapper>
      
    • 解决方式三: 利用<resultMap id="" type="">映射配置</resultMap>标签

      id:唯一标识此 resultMap 的 ID,一般命名为目标Java类名+ResultMap,即id = “brandResultMap”

      type:指定结果映射的目标 Java 类的完全限定名(全类名)(注意:支持使用别名)。MyBatis 会将查询结果映射到这个类的实例。此处type = "at.guigu.pojo.Brand"type = "brand"

      • 解释:用于定义一个**结果映射** ,指定如何将 SQL 查询结果集中的列映射到 Java 对象的属性。

      • 可用的标签体标签体

        标签体解释
        <id property= "Java类属性名" column="SQL字段名">标识主键列
        <result property="Java类属性名" column="SQL字段名"/>标识非主键列
        <association property="Java类属性名" javaType="java类全类名"></association>处理嵌套对象的映射,可以嵌套 <resultMap> 标签或者其他 <result>, <id> 标签
        <collection property="Java类属性名" ofType="com.example.Order"></collection>处理嵌套集合的映射,可以嵌套 <resultMap> 标签或者其他 <result>, <id> 标签。(注意:ofType的属性值为:集合中元素的 Java 类型。)
      • 具体过程详见如下xml文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
          
      <!--将resultType改为resultMap且属性值为resultMap标签中id的属性值-->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
      </mapper>
      
查看详情

在这里插入图片描述

  • 解释

    查看详情是通过返回对应的序号给后台,然后后台通过id找到对应数据传输到前端供浏览者获取信息,由于一个id对应一个品牌的信息,所以返回的是一个对象

    Mapper接口中定义的方法为Brand selectById(int id);

    SQL映射文件中的SQL语句为

    <select id="selectById" parameterType="int" resultMap="brandResultMap">
    	select * from tb_brand where id = #{id};
        <!--#{id}用于接收传入的参数,相当于
    	select * from tb_brand where id = ?;
    	-->
    </select>
    
    • 注意:参数占位符来代替要传入SQL语句的参数

      • #{} :可放置SQL注入

      • ${} :存在SQL注入问题(最好不要用这个参数占位符,只有在表名或列名不固定的情况下才使用该参数占位符)

        select * from tb_brand where id = ${id};
        <!--假设传入参数为1则相当于select * from tb_brand where id = 1;-->
        
    • 注意2:<select></select>标签中的属性parameterType可设置传入的参数类型 ,它可以省略不写

    • 注意3:特殊字符处理(可详见day18XML知识点)

      • 利用转义字符:即XML文件中的特殊字符

        1. &lt;------<------小于
        2. &gt;------>------大于
        3. &amp;------&------和号
        4. &apos;------'------单引号
        5. &quot;------"------引号
        <!--    查看详情-->
            <select id="selectById" parameterType="int" resultMap="brandResultMap">
                select * from tb_brand where id &gt #{id};
            </select>
        
      • 将特殊字符写在CDATA

        <!--    查看详情-->
        <select id="selectById" parameterType="int" resultMap="brandResultMap">
                select * from tb_brand where id <![CDATA[
                >
                ]]>
                #{id};
            </select>
        
      • 特殊字符比较少时用转义字符,反之则用CDATA区

  • 完整代码如下

    • SQL映射文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName" />
              <result column="company_name" property="companyName" />
          </resultMap>
      
          <!--查询所有数据-->
          <select id="selectAll" resultMap="brandResultMap">
              select * from tb_brand;
          </select>
      
          <!--    查看详情-->
          <select id="selectById" parameterType="int" resultMap="brandResultMap">
              select * from tb_brand where id = #{id};
          </select>
      
      </mapper>
      
    • 接口

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import org.apache.ibatis.annotations.Param;
      
      import java.util.List;
      import java.util.Map;
      
      public interface BrandMapper {
          //查询所有数据
          List<Brand> selectAll();
          //查看详情
          Brand selectById(int id);
      }
      
    • 测试代码

      package at.guigu.test;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      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 org.junit.Test;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class MyBatisTest {
          private static BrandMapper getBrandMapper() throws IOException {
              //1 加载核心配置文件,获取`SqlSessionFactory`对象
              //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
              String resource = "mybatis-config.xml";
              //1.2 利用Resources类中的静态方法将配置文件加载到内存
              InputStream inputStream = Resources.getResourceAsStream(resource);
              //1.3 获取SqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              return brandMapper;
          }
      
          //查询所有数据
          @Test
          public void testSelectAll() throws IOException {
              //获取Mapper接口对象
              BrandMapper brandMapper = getBrandMapper();
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectAll();
              System.out.println(brands);
          }
      
          //查看详情
          @Test
          public void testSelectById() throws IOException {
              int id = 1;//接收前端传回的序号
              //获取Mapper接口对象
              BrandMapper brandMapper = getBrandMapper();
              //2.3 执行sql语句
              Brand brands = brandMapper.selectById(id);
              System.out.println(brands);
          }
      }
      
普通多条件查询

在这里插入图片描述

在这里插入图片描述

  • 编写接口方法的方式有三种

    在这里插入图片描述

    • 方式一散装参数接收: 定义含多个参数的接口方法时,要通过@Param("参数")注解来将对应的方法参数放到SQL映射文件中SQL语句对应的参数占位符上,其中注解参数名称要和SQL映射文件中SQL语句中的参数占位符名称对应一致
    • 方式二对象参数接收: 若三个参数都属于同一个对象的话则可以将它们封装成一个对象,然后将对象作为一个参数,即List<Brand> selectByCondition(Brand brand),此时SQL映射文件中SQL语句对应的参数占位符会自动从对象中找对应的值(前提是对象中的属性名称要和SQL语句中参数占位符名称一致)
    • 方式三Map集合参数接收: 可将以上三个参数封装到Map集合中作为键,并给其对应的键值,然后将Map集合作为一个参数,即List<Brand> selectByCondition(Map map),此时SQL映射文件中SQL语句对应的参数占位符会自动从对象中找对应的值(前提是Map集合中的键名要和SQL语句中参数占位符名称一致)
    • 以上三种方式在SQL映射文件中SQL语句的写法是一样的,如下,不一样的是接口中使用了方法重载以及运行的代码
  • 完整代码如下

    • SQL映射文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <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>
      
      </mapper>
      
    • Mapper接口

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import org.apache.ibatis.annotations.Param;
      
      import java.util.List;
      import java.util.Map;
      
      public interface BrandMapper {
          //查询所有数据
          List<Brand> selectAll();
          //查看详情
          Brand selectById(int id);
          //多条件查询方式一:散装参数接收
          List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
          //多条件查询方式二:对象参数接收
          List<Brand> selectByCondition(Brand brand);
          //多条件查询方式三:Map集合参数接收
          List<Brand> selectByCondition(Map map);
      }
      
    • 测试代码

      package at.guigu.test;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      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 org.junit.Test;
      
      import java.io.IOException;
      import java.io.InputStream;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class MyBatisTest {
          private static BrandMapper getBrandMapper() throws IOException {
              //1 加载核心配置文件,获取`SqlSessionFactory`对象
              //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
              String resource = "mybatis-config.xml";
              //1.2 利用Resources类中的静态方法将配置文件加载到内存
              InputStream inputStream = Resources.getResourceAsStream(resource);
              //1.3 获取SqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              return brandMapper;
          }
      
          //多条件查询方式一:散装参数接收
          @Test
          public void testSelectByCondition() throws IOException {
              //接收前端传回的多条件参数
              int status = 1;
              String companyName = "华为";
              String brandName = "华为";
              //处理参数
              companyName = "%" + companyName + "%";
              brandName = "%" + brandName + "%";
              //获取Mapper接口对象
              BrandMapper brandMapper = getBrandMapper();
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
              System.out.println(brands);
          }
          //多条件查询方式二:对象参数接收
          @Test
          public void testSelectByConditionTwo() 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);
              //获取Mapper接口对象
              BrandMapper brandMapper = getBrandMapper();
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectByCondition(brand);
              System.out.println(brands);
          }
          //多条件查询方式三:Map集合参数接收
          @Test
          public void testSelectByConditionThree() throws IOException {
              //接收前端传回的多条件参数
              int status = 1;
              String companyName = "华为";
              String brandName = "华为";
              //处理参数
              companyName = "%" + companyName + "%";
              brandName = "%" + brandName + "%";
              //将多条件参数封装到对象中
              Map map = new HashMap();
              map.put("status", status);
              map.put("companyName", companyName);
              map.put("brandName", brandName);
              //获取Mapper接口对象
              BrandMapper brandMapper = getBrandMapper();
              //2.3 执行sql语句
              List<Brand> brands = brandMapper.selectByCondition(map);
              System.out.println(brands);
          }
      }
      
动态多条件查询

普通多条件查询时,多个条件若缺少其中一个条件(即用户输入条件时不一定会将所有条件都填写)则会导致查询失败,会解决该问题引入了动态多条件查询

  • 特点

    • SQL映射文件中的SQL语句会随着用户的输入或外部条件的变化而变化,称为动态SQL(MyBatis对动态SQL有强大的支撑)
  • MyBatis提供给动态SQL的标签如下

    标签解释
    <if test="逻辑表达式"></if>条件标签,使用test属性进行条件判断
    choose(when, otherwise)条件选择标签,类似于Java中的switch语句
    trim(where, set)
    foreach
    • if标签:常用于判断参数是否有值,使用test属性进行条件判断
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <!--namespace:名称空间-->
    <mapper namespace="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <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 companyName != ''">
                    and company_name like #{companyName}
                </if>
                <if test="brandName != null and brandName != ''">
                    and brand_name like #{brandName}
                </if>
        </select>
    
    </mapper>
    

    if标签缺点: 多条件动态查询时除了第一个参数不能为空外,其它参数都可为空,因为SQL映射文件中不同SQL语句的条件之间通过and连接,此时假设第一个参数为null,则动态SQL语句就变为了select * from tb_brand where and company_name like ?,该SQL语句是个错误形式,因为where关键字后直接跟了and

    • 解决方式一: 创建恒等式,如下所示

      此时无论三个条件是否满足都不会造成SQL语句形式出错,因为此时where关键字后的第一个条件1 = 1是必然成立的

          <!--多条件查询-->
          <select id="selectByCondition" resultMap="brandResultMap">
              select * from tb_brand
              where 1 = 1
                  <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>
      
    • 解决方式二: 利用MyBatis提供的<where>标签来替换SQL的where关键字,如下所示

      • where标签特点

        ​ 1.会根据实际情况自动去除and关键字构成正确的SQL语句

        ​ 2.若无任何条件该标签会自动去除SQL语句中的where关键字,即此时动态SQL语句就变为select * from tb_brand;

          <!--多条件查询-->
          <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>
              </where>
          </select>
      
动态单条件查询------choose(when, otherwise)

在这里插入图片描述

  • 解释

    从多个条件中选择一个条件进行查询

  • 注意

    • choose标签类似于switch
    • when标签类似于case
    • otherwise标签相当于switch语句中的default
  • 对应的SQL映射文件如下

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <!--namespace:名称空间-->
    <mapper namespace="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--动态单条件查询-->
        <select id="selectBySingleCondition" resultMap="brandResultMap">
            select * from tb_brand
            where
            <choose> <!--类似于switch-->
                <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>
                <otherwise><!--相等于default,即若条件都没选则执行otherwise标签体的内容-->
                    1=1
                </otherwise>
            </choose>
        </select>
    
    </mapper>
    
    • 注意:在以上SQL映射文件中,若三个条件都没选则会执行default语句的代码,此时SQL语句为select * from where 1=1;,可能会返回错误的结果,所以可将<choose>标签放在<where>标签中来解决该问题,如下所示**( 推荐使用 ,where标签的特点详见动态多条件查询 )**

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName" />
              <result column="company_name" property="companyName" />
          </resultMap>
      
          <!--动态单条件查询-->
          <select id="selectBySingleCondition" resultMap="brandResultMap">
              select * from tb_brand
              <where>
                  <choose> <!--类似于switch-->
                      <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>
      </mapper>
      

添加

基础添加

在这里插入图片描述

  • 解释:它会将网页要添加的数据封装成一个对象,然后添加到数据库表中

  • 注意:添加时,id不会让用户自己写,这个是自动生成的,所以参数是除了id之外的所有数据

  • SQL映射文件如下:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    <!--namespace:名称空间-->
    <mapper namespace="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--基础添加-->
        <insert id="add">
            insert into tb_brand (brand_name, company_name, ordered, description, status)
            values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
        </insert>
    </mapper>
    
  • 接口如下

    package at.guigu.mapper;
    
    import at.guigu.pojo.Brand;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    import java.util.Map;
    
    public interface BrandMapper {
        //基础添加
        void add(Brand brand);
    }
    
  • 测试代码如下

    package at.guigu.test;
    
    import at.guigu.mapper.BrandMapper;
    import at.guigu.pojo.Brand;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisTest {
        //基础添加
        @Test
        public void testAdd() throws IOException {
            //接收前端传回的多个参数
            String companyName = "波导";
            String brandName = "波导手机";
            String description = "手机中的战斗机";
            int ordered = 100;
            int status = 1;
    
            //将参数封装到对象中
            Brand brand = new Brand();
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
            brand.setStatus(status);
    
            //1 加载核心配置文件,获取`SqlSessionFactory`对象
            //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
            String resource = "mybatis-config.xml";
            //1.2 利用Resources类中的静态方法将配置文件加载到内存
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //1.3 获取SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2 获取SqlSession对象,执行SQL语句
            //2.1 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //2.2 获取Mapper接口UserMapper的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
            //2.3 执行sql语句
            brandMapper.add(brand);
            //手动提交事务
            sqlSession.commit();
            //3 释放资源
            sqlSession.close();
        }
    }
    

    手动提交事务的原因: 若无手动提交事务的代码则运行时能够运行成功但是数据库对应的表中并没有数据,原因是自动提交事务被关闭,所以我们需要手动提交事务,此时数据库的表中就会出现添加的数据,如图所示

    在这里插入图片描述

    • 注意:若不想在最后手动提交事务,则可在获取SqlSession对象时将事务自动提交开启,即SqlSession sqlSession = sqlSessionFactory.openSession(true);代表将参数autoCommit设置为true(即开启事务自动提交)
  • 问题:添加数据时会自动在数据库表中添加两条重复数据,如图所示,解决方法如下

    在这里插入图片描述

    在这里插入图片描述

主键返回
  • 解释

    在数据添加成功后需要获取插入数据库数据的主键的值(比如我在基础添加中添加了一个商品,现在添加成功后需要获取对应的主键值即id)

  • 注意

    • 在基础添加中的示例(添加了一个波导手机),由于id属于主键且课可以自增,所以在添加商品时不需要用户来添加id,而是系统自动添加id,所以用户需要输入的数据是除了主键id之外的所有数据,且这些数据是被封装到对象中然后通过若干方法最终到达数据库的,这就会有一个问题:添加商品成功后,无法通过Brand对象返回对应的id,这是因为并没有将对应的id封装到该对象中去,所以也就无法通过对象来获取用户添加的商品的对应主键id

    • 解决方法:将主键绑定到对象上,SQL映射文件如下:

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName" />
              <result column="company_name" property="companyName" />
          </resultMap>
      
          <!--主键返回-->
          <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>
      </mapper>
      
      属性解释
      useGeneratedKeys是否将主键绑定到对象,默认为false
      keyProperty="name"数据库表的主键对应对象中属性的名称(即将主键与对象中的name属性关联)
    • 测试代码为

      package at.guigu.test;
      
      import at.guigu.mapper.BrandMapper;
      import at.guigu.pojo.Brand;
      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 org.junit.Test;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      public class MyBatisTest {
          //基础添加
          @Test
          public void testAdd() throws IOException {
              //接收前端传回的多个参数
              String companyName = "波导";
              String brandName = "波导手机";
              String description = "手机中的战斗机";
              int ordered = 100;
              int status = 1;
      
              //将参数封装到对象中
              Brand brand = new Brand();
              brand.setCompanyName(companyName);
              brand.setBrandName(brandName);
              brand.setDescription(description);
              brand.setOrdered(ordered);
              brand.setStatus(status);
      
              //1 加载核心配置文件,获取`SqlSessionFactory`对象
              //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
              String resource = "mybatis-config.xml";
              //1.2 利用Resources类中的静态方法将配置文件加载到内存
              InputStream inputStream = Resources.getResourceAsStream(resource);
              //1.3 获取SqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
              //2 获取SqlSession对象,执行SQL语句
              //2.1 获取SqlSession对象
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //2.2 获取Mapper接口UserMapper的代理对象
              BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
              //2.3 执行sql语句
              brandMapper.add(brand);
              //手动提交事务
              sqlSession.commit();
              //3 释放资源
              sqlSession.close();
          }
      }
      

      在这里插入图片描述

修改

  • 解释:修改(即编辑)已存在的商品数据信息

在这里插入图片描述

修改全部字段
  • SQL映射文件

    <?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="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--修改商品数据:修改全部字段-->
        <update id="update">
            update tb_brand
            set brand_name=#{brandName},
                company_name=#{companyName},
                ordered=#{ordered},
                description=#{description},
                status=#{status}
            where id=#{id};
        </update>
    </mapper>
    
  • 接口

    package at.guigu.mapper;
    
    import at.guigu.pojo.Brand;
    import org.apache.ibatis.annotations.Param;
    
    public interface BrandMapper {
        //修改数据:修改全部字段   并返回受影响的行数
        int update(Brand brand);
    }
    
  • 测试代码

    import at.guigu.mapper.BrandMapper;
    import at.guigu.pojo.Brand;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisTest {
            //修改全部字段
        @Test
        public void testUpdate() throws IOException {
            //接收前端传回的多个参数
            int id = 4;
            String companyName = "波导岛搭";
            String brandName = "波导岛手机的";
            String description = "手机中的战斗大机积极";
            int ordered = 90;
            int status = 1;
    
            //将参数封装到对象中
            Brand brand = new Brand();
            brand.setId(id);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
            brand.setStatus(status);
    
            //1 加载核心配置文件,获取`SqlSessionFactory`对象
            //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
            String resource = "mybatis-config.xml";
            //1.2 利用Resources类中的静态方法将配置文件加载到内存
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //1.3 获取SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2 获取SqlSession对象,执行SQL语句
            //2.1 获取SqlSession对象并开启事务自动提交
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            //2.2 获取Mapper接口UserMapper的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
            //2.3 执行sql语句并返回受影响的行数
            System.out.println(brandMapper.update(brand));
    
            //3 释放资源
            sqlSession.close();
        }
    }
    

    在这里插入图片描述

    在这里插入图片描述

修改动态字段
  • 解释:用户将来修改的字段是不固定的,不可能提前知道要修改的字段名,此时就需要用到该技术

  • 利用<set>标签,特点

    • 该标签会自动判断是否有修改的字段,若无任何修改的字段则生成的动态SQL语句就不会有set关键字,若某个字段未被修改则生成的动态SQL语句会自动忽略该字段修改语句以及该字段修改语句后的逗号,以映射文件中SQL语句为例:
      • 假设现在无任何修改字段,则动态SQL语句变为:update tb_brand where id = ?;
      • 假设现在只有字段description被修改则动态SQL语句变为:update tb_brand where description = ? where id = ?;
  • SQL映射文件中SQL语句如下

    <?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="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--修改商品数据:修改动态字段-->
        <update id="updatePart">
            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>
    </mapper>
    
  • 接口

    package at.guigu.mapper;
    
    import at.guigu.pojo.Brand;
    import org.apache.ibatis.annotations.Param;
    
    
    public interface BrandMapper {
        //修改数据:修改部分字段,即修改动态字段  并返回受影响的行数
        int updatePart(Brand brand);
    }
    
  • 测试代码

    import at.guigu.mapper.BrandMapper;
    import at.guigu.pojo.Brand;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisTest {
            //修改全部字段
        @Test
        public void testUpdate() throws IOException {
            //接收前端传回的多个参数
            int id = 4;
            String companyName = "波导岛搭";
            String brandName = "波导岛手机的";
            String description = "手机中的战斗大机积极";
            int ordered = 90;
            int status = 1;
    
            //将参数封装到对象中
            Brand brand = new Brand();
            brand.setId(id);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
            brand.setStatus(status);
    
            //1 加载核心配置文件,获取`SqlSessionFactory`对象
            //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
            String resource = "mybatis-config.xml";
            //1.2 利用Resources类中的静态方法将配置文件加载到内存
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //1.3 获取SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2 获取SqlSession对象,执行SQL语句
            //2.1 获取SqlSession对象并开启事务自动提交
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            //2.2 获取Mapper接口UserMapper的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
            //2.3 执行sql语句并返回受影响的行数
            System.out.println(brandMapper.updatePart(brand));
    
            //3 释放资源
            sqlSession.close();
        }
    }
    

    在这里插入图片描述

删除

删除一个
  • 解释:删除一条数据(商品)

  • SQL映射文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--namespace:名称空间-->
    <mapper namespace="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--删除一条数据(删除一个商品)-->
        <delete id="delete">
            delete from tb_brand where id = #{id};
        </delete>
    </mapper>
    
  • Mapper接口

    package at.guigu.mapper;
    
    import at.guigu.pojo.Brand;
    import org.apache.ibatis.annotations.Param;
    
    public interface BrandMapper {
        //删除一条数据(删除一个商品)并判断删除是否成功
        boolean delete(int id);
    }
    
  • 测试代码

    import at.guigu.mapper.BrandMapper;
    import at.guigu.pojo.Brand;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisTest {
            //修改全部字段
        @Test
        public void testSingleDelete() throws IOException {
            //接收前端传回的参数
            int id = 4;
    
            //1 加载核心配置文件,获取`SqlSessionFactory`对象
            //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
            String resource = "mybatis-config.xml";
            //1.2 利用Resources类中的静态方法将配置文件加载到内存
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //1.3 获取SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2 获取SqlSession对象,执行SQL语句
            //2.1 获取SqlSession对象并开启事务自动提交
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            //2.2 获取Mapper接口UserMapper的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
            //2.3 执行sql语句并返回受影响的行数
            System.out.println(brandMapper.delete(id));
    
            //3 释放资源
            sqlSession.close();
        }
    }
    

    在这里插入图片描述

批量删除
  • 解释:一次删除多条数据(商品)

  • 注意

    删除多条数据时会根据id进行删除,并且会将id封装到数组中,通过遍历数组依次删除对应的数据(商品)

  • 用到的标签及属性

    标签解释
    <foreach></foreach>用于循环处理一组数据的标签。常用于在模板文件中循环遍历一个集合,例如列表或数组,并对集合中的每一项执行某些操作
    该标签中的属性解释
    collectionitems指定要迭代的集合或数组。
    itemvar指定循环中每次迭代时的当前项变量名称
    separator指定在每次迭代之间插入的字符串或标记
    open指定在循环开始时添加的字符串或标记
    close指定在循环结束时添加的字符串或标记
  • SQL映射文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--namespace:名称空间-->
    <mapper namespace="at.guigu.mapper.BrandMapper">
        <!--结果映射-->
        <resultMap id="brandResultMap" type="brand">
            <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!--批量删除-->
        <delete id="deleteByIds">
            delete from tb_brand where id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </delete>
    </mapper>
    
    • 注意

      由于数组中id个数不确定,所以需要用到<foreach>标签来遍历数组,并将遍历到的参数之间用隔开,最终放在()内,假设现在数组ids中有三个id,则动态SQL语句为delete from tb_brand where id in(?,?,?);

  • 接口

    package at.guigu.mapper;
    
    import at.guigu.pojo.Brand;
    import org.apache.ibatis.annotations.Param;
    
    public interface BrandMapper {
        //批量删除
        boolean deleteByIds(@Param("ids") int[] ids);
    }
    
  • 测试代码

    import at.guigu.mapper.BrandMapper;
    import at.guigu.pojo.Brand;
    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 org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MyBatisTest {
        //批量删除
        @Test
        public void testDelete() throws IOException {
            //接收前端传回的参数
            int[] ids = {2,3};
    
            //1 加载核心配置文件,获取`SqlSessionFactory`对象
            //1.1 配置mybatis-config.xml文件路径,由于该文件直接在resources目录下,所以直接写文件名即可
            String resource = "mybatis-config.xml";
            //1.2 利用Resources类中的静态方法将配置文件加载到内存
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //1.3 获取SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //2 获取SqlSession对象,执行SQL语句
            //2.1 获取SqlSession对象并开启事务自动提交
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            //2.2 获取Mapper接口UserMapper的代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
            //2.3 执行sql语句并返回受影响的行数
            System.out.println(brandMapper.deleteByIds(ids));
    
            //3 释放资源
            sqlSession.close();
        }
    }
    

    在这里插入图片描述

  • 注意:SQL映射文件与对应接口有两种方式,以上示例中是一种方式,以下将对另一种方式进行说明

    • 由于MyBatis会自动将数组参数封装为一个Map集合,默认情况下该Map集合中键名为array,键值为传入的数组,所以SQL映射文件和接口也可写为如下形式

    • SQL映射文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <!--namespace:名称空间-->
      <mapper namespace="at.guigu.mapper.BrandMapper">
          <!--结果映射-->
          <resultMap id="brandResultMap" type="brand">
              <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可-->
              <result column="brand_name" property="brandName" />
              <result column="company_name" property="companyName" />
          </resultMap>
      
          <!--批量删除-->
          <delete id="deleteByIds">
              delete from tb_brand where id in
              <foreach collection="array" item="id" separator="," open="(" close=")">
                  #{id}
              </foreach>
          </delete>
      </mapper>
      
    • 接口

      package at.guigu.mapper;
      
      import at.guigu.pojo.Brand;
      import org.apache.ibatis.annotations.Param;
      
      public interface BrandMapper {
          //批量删除
          boolean deleteByIds(int[] ids);
      }
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/750724.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI 开发平台(Coze)搭建《美食推荐官》

前言 本文讲解如何从零开始&#xff0c;使用扣子平台去搭建《美食推荐官》 bot直达&#xff1a;美食推荐官 - 扣子 AI Bot (coze.cn) 欢迎大家体验一下&#xff01;&#xff01; 效果 正文 prompt 美食推荐官的首要任务就是推荐美食&#xff0c;基于这个我们要给他一个基…

【图像分类】Yolov8 完整教程 |分类 |计算机视觉

目标&#xff1a;用YOLOV8进行图像分类。 图像分类器。 学习资源&#xff1a;https://www.youtube.com/watch?vZ-65nqxUdl4 努力的小巴掌 记录计算机视觉学习道路上的所思所得。 1、文件结构化 划分数据集&#xff1a;train,val,test 知道怎么划分数据集很重要。 文件夹…

SQL注入漏洞—SQL注入简介与原理

一、SQL注入基础 1.1 什么是SQL注入漏洞 SQL注入漏洞从1998年圣诞节大火以来长盛不衰&#xff0c;虽然开发人员想出各种方法对他进行围追堵截&#xff0c;却始终无法将其赶尽杀绝&#xff0c;SQL注入的根本原因就是将SQL代码插入或添加到应用&#xff08;用户&#xff09;的输…

算法08 广/宽度优先搜索及相关问题详解

这是《C算法宝典》算法篇的第08节文章啦~ 如果你之前没有太多C基础&#xff0c;请点击&#x1f449;专栏&#xff1a;C语法入门&#xff0c;如果你C语法基础已经炉火纯青&#xff0c;则可以进阶算法&#x1f449;专栏&#xff1a;算法知识和数据结构&#x1f449;专栏&#xff…

2024三掌柜赠书活动第二十五期:Rust 游戏开发实战

目录 目录 前言 Rust语言概念 关于《Rust 游戏开发实战》 Rust系统编程的核心点 Rust开发的关键技术和工具 内容简介 作者简介 书中前言/序言 内容介绍 《Rust 游戏开发实战》全书速览 图书目录 结束语 前言 技术圈最近的编程语言新秀当属Rust莫属&#xff0c;Rus…

祝贺!FISCO BCOS伙伴科大讯飞获国家科学技术进步奖一等奖

6月24日&#xff0c;2023年度国家科学技术奖励大会在京召开&#xff0c;金链盟理事单位、开源工作组成员单位、FISCO BCOS产业应用合作伙伴科大讯飞作为第一完成单位的“多语种智能语音关键技术及产业化”项目获得国家科学技术进步奖一等奖。 这是深度学习引发全球人工智能浪潮…

多路h265监控录放开发-(14)通过PaintCell自定义日历控件继承QCalendarWidget的XCalendar类

首先创建一个新类XCalendar继承QCalendarWidget类&#xff0c;然后在UI视图设计器中把日历提升为XCalendar&#xff0c;通过这个函数自己设置日历的样式 xcalendar.h #pragma once #include <QCalendarWidget> class XCalendar :public QCalendarWidget { public:XCal…

“一站式企业服务平台”全景解析

在当今市场竞争日益激烈、商业环境瞬息万变的大经济环境下&#xff0c;企业在经营过程中常常面临政策不知道摸不清、资源获取困难、融资渠道狭窄、市场开拓不畅、政务办理繁琐等诸多问题&#xff0c;为了解决这些问题&#xff0c;帮扶企业发展&#xff0c;同时优化区域营商环境…

【Spring】SpringCloudAlibaba学习笔记

Nacos Nacos是一个更易于构建云原生应用的动态服务发现/服务配置和服务管理平台核心功能: 服务注册: Nacos Client会通过发送REST请求向Nacos Server注册自己的服务, 提供自己的元数据, 如ip地址/端口等信息; Nacos Server收到注册请求后, 就会把这些信息存储在Map中服务心跳:…

前端基础--Vue2

前端技术发展史(了解) 1.前端历史 1.1.静态网页 1990 html 1.2.异步刷新-操作dom 1995 javascript 1.3.动态网站 Asp/jsp&#xff08;java&#xff09;,php等&#xff0c;后台臃肿 1.4.Ajax成为主流 异步请求 1.5.Html5 被认为是互联网的核心技术之一。HTML产生于19…

12,SPI

Flash芯片&#xff1a;W25Q64&#xff0c;可以看成一个储存器 W25Q64芯片和单片机之间的通信方式是SPI SPI:串行同步全双工&#xff0c;主从通信 判断一个设备是不是SPI通信&#xff0c;看是否有这几个线&#xff1a;SCK&#xff0c;CS&#xff0c;MISO&#xff0c;MOSI SCK…

探索Android架构设计

Android 应用架构设计探索&#xff1a;MVC、MVP、MVVM和组件化 MVC、MVP和MVVM是常见的三种架构设计模式&#xff0c;当前MVP和MVVM的使用相对比较广泛&#xff0c;当然MVC也并没有过时之说。而所谓的组件化就是指将应用根据业务需求划分成各个模块来进行开发&#xff0c;每个…

Three.js鼠标拖动设置骨骼姿态

实现 根据SkinnedMesh生成Mesh 作为射线检测的目标&#xff08;射线检测SkinnedMesh存在不足 无法应用骨骼形变的顶点 &#xff09;点击模型 获取点击位置对应的骨骼拖拽鼠标设置骨骼旋转角度&#xff08;使用TransformControl选中点击的骨骼 设置轴为XYZE 并隐藏控件 主动触发…

马面裙的故事:汉服如何通过直播电商实现产业跃迁

【潮汐商业评论/原创】 波澜壮阔的千里江山在马面裙的百褶上展开&#xff0c;织金花纹在女性的步伐之间若隐若现&#xff0c;从明清到现代&#xff0c;如今马面裙又流行了回来&#xff0c;成为女性的流行单品&#xff0c;2024年春节期间&#xff0c;马面裙更是成为华夏女孩们的…

仓库管理系统14--仓库设置

1、添加窗体 <UserControl x:Class"West.StoreMgr.View.StoreView"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc"http://schemas.openxmlformats.…

Str.format()方法

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 在Python2.6之后&#xff0c;提供了字符串的format()方法对字符串进行格式化操作。format()功能非常强大&#xff0c;格式也比较复杂&…

选择第三方软件测试机构做验收测试的好处简析

企事业单位在自行开发完软件系统或委托软件开发公司生产软件之后&#xff0c;有一个必经流程就是验收测试&#xff0c;以验证该产品是否符合用户需求、是否可以上线。为了客观评估所委托生产的软件质量&#xff0c;第三方软件测试机构往往成为企事业单位做验收测试的首选&#…

Bad owner or permissions on C:\\Users\\username/.ssh/config > 过程试图写入的管道不存在。

使用windows连接远程服务器出现Bad owner or permissions 错误 问题&#xff1a; 需要修复文件权限 SSH 配置文件应具有受限权限以防止未经授权的访问 确保只有用户对该.ssh/config文件具有读取权限 解决方案&#xff1a; 在windows下打开命令行&#xff0c;通过以下命令打开文…

PS使用批量脚本生成海报实践

前言 设计朋友有需求做一批邀请函&#xff0c;有几十个人名&#xff0c;需要把人名加到海报中&#xff0c;PS里一个一个添加人名很麻烦&#xff0c;于是来问我有没有什么办法能够批量去添加。 希望把人名加到红框区域内 尝试用ps的脚本进行处理 准备 PS(版本2021&#xff0c;…

HTML静态网页成品作业(HTML+CSS)——企业摄影网介绍网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有3个页面。 二、作品演示 三、代…