Mybatis简单入门

在这里插入图片描述
                       星光下的赶路人star的个人主页

                      夏天就是吹拂着不可预期的风

文章目录

  • 1、Mybatis介绍
    • 1.1 JDBC痛点
    • 1.2 程序员的诉求
      • 1.3 Mybatis简介
  • 2、数据准备
    • 2.1 数据准备
    • 2.2 建工程
    • 2.3 Employee类
    • 2.4 Mybatis的全局配置
    • 2.5 编写要执行的SQL
    • 2.6 编写java程序
    • 2.7 稍微总结一下流程
  • 3、解决属性无法封装的问题
    • 4、接口式编程
    • 4.1 编写Dao层接口
    • 4.2 编写Mapper所使用的SQL(EmployeeMapper.xml)
    • 4.3 接口式编程的使用步骤
    • 4.4 测试代码
    • 4.5 注解接口式编程
  • 5、ResultMap
  • 6、引入Sql模板
    • 7、获取接口方法入参
    • 8、Sql注入
  • 9、动态SQL

1、Mybatis介绍

MyBatis(原名为iBatis)是一种开源的持久层框架,它简化了在Java应用程序中的数据库访问。MyBatis通过将数据库查询和映射任务从Java代码中分离出来,提供了一种灵活且强大的方式来处理数据持久化。

1.1 JDBC痛点

在这里插入图片描述
JDBC是Java中对数据库进行读写的标准,原生JDBC的痛点在于:

  • SQL夹在Java代码中,耦合度高导致每次修改SQL都需要重新测试,编译,打包,部署,维护不易。
  • 大量冗余的模板代码,编写起来费力。

1.2 程序员的诉求

对于开发人员来说,我们希望掌握核心科技,即SQL是由我们编写的,而其他脏活和累活由框架为我们自动完成。

在这里插入图片描述
除此之外,我们还希望SQL和java代码分离,保持低耦合。这样在频繁需要修改SQL的场景下,只需要修改SQL语句的编码文件,而无需更改java源代码,简化部署流程。
在这里插入图片描述

1.3 Mybatis简介

MyBatis是一个java编写的轻量级(使用方式简单)的半自动(sql自己写,其他框架做)的ORM映射的Dao层框架,
Dao(DataBase Access Object):指java程序中专门用于访问数据库的对象:
在这里插入图片描述
ORM(Object Relation Mapping):指将java程序中封装数据的Bean和数据库中的保存数据的表结构进行映射。
在这里插入图片描述
ORM的规则中:

  • 一种Bean对应一张表
  • Bean的一个属性对应表中的一列
  • 一个Bean对应数据库中的一行
  • 读数据库即是把表中的行封装为一个Bean
  • 写数据库就是把Bean中的属性写入到表中

2、数据准备

以查询数据库中指定id的员工为例

2.1 数据准备

CREATE DATABASE `Mybatis` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE TABLE employee(
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  last_name VARCHAR(255),
  gender VARCHAR(10),
  email VARCHAR(255)
);
INSERT INTO employee(last_name,gender,email) VALUES('Tom','male','Tom@163.com');
INSERT INTO employee(last_name,gender,email) VALUES('Jack','male','Jack@163.com');
INSERT INTO employee(last_name,gender,email) VALUES('Marry','female','Tom@163.com');

2.2 建工程

创建IDEAproject,在相关的module的pom中添加如下依赖:

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        
 <!-- mysql数据驱动包 -->       
      <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>
<!-- bean -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
<!-- 测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

<!-- 打印日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

2.3 Employee类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer id;
    private String lastName;
    private String gender;
    private String email;
    
}

2.4 Mybatis的全局配置

在resources目录下加入MyBatis的全局配置文件(根据自己的配置要修改)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 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.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://hadoop102:3306/Mybatis?serverTimezone=Asia/Shanghai&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="000000"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

2.5 编写要执行的SQL

myba的优点在于java代码和sql语句分离。sql语句编写在xml文件中,同时注意需要再全局配置文件中注册
在resources中添加存放sql语句的xml配置文件
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="good">
    <select id="a" resultType="com.zhm.mybatis.beans.Employee">
    select * from employee where id = #{id}
  </select>

</mapper>

之后需要再全局的配置中注册,即让MyBatis可以通过指定的xml文件找到辨析的sql。在mybatis.xml的最后位置添加如下内容

<mappers>
        <mapper resource="sql.xml"/>
</mappers>

如果希望在控制台看到发送的sql语句,可以在resources下添加log4j.xml文件。内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n" />
        </layout>
    </appender>
    <logger name="java.sql">
        <level value="debug" />
    </logger>
    <logger name="org.apache.ibatis">
        <level value="info" />
    </logger>
    <root>
        <level value="debug" />
        <appender-ref ref="STDOUT" />
    </root>
</log4j:configuration>

2.6 编写java程序

public class MybatisDemo1
{
    public static void main(String[] args) throws IOException {

        //读取配置文件
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        /*
            发送sql  查询某个id的员工
                selectOne(String statement, Object parameter)
                    statement: sql语句。使用 namespace.id的方式来引用
                    parameter: 语句中传入的参数
         */
       /* Object o = sqlSession.selectOne("good.a", inputStream);
        Employee employee = (Employee) o;*/

        // 泛型方法的调用:  对象.<泛型类型>方法()
        Employee employee = sqlSession.<Employee>selectOne("good.a", 1);
        System.out.println(employee);

        sqlSession.close();

    }
}

运行截图:
在这里插入图片描述

2.7 稍微总结一下流程

1、首先是要在mysql中有表
2、根据表的信息来创建对应的Bean
3、然后如果没有MyBatis的全局配置就配置一个
4、在resources中编写一个要执行的sql配置文件
5、编写java程序测试能不能从数据库中将数据封装为Bean

3、解决属性无法封装的问题

眼神好的小伙伴应该已经看出,我上一步执行的程序是有问题的,运行结果中的对象的lastName的值是null,但是在数据库中却不是null。

这就是要涉及java的规范和mysql库的规范扯上关系了,java的属性一般是驼峰式命名的,但是mysql却是下划线作为分隔符的,这就会导致java在生成某个属性方法式也是利用驼峰式生成的方法(举个例子吧,比如Employee中的lastname想要和数据库中的last_name映射上就得设置映射规则)
在mybatis.xml中添加如下配置:

 <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
 </settings>

注意:这个配置是有顺序的比较前
解释:配置了这个MyBatis在映射的时候就会把下划线转为驼峰式的映射规则
运行截图:
在这里插入图片描述

4、接口式编程

使用MyBatis原生API进行开发有以下不便之处:

  • 我们更倾向于使用Dao—DaoImpl来分层解耦
  • 方法的返回值是Object类型,不能直接使用,需要强转
  • 方法的入参无法进行严格的检查

在此,推荐使用接口式编程开发。即在接口中明确Dao层对象方法的参数类型和返回值类型,通过接口中的Dao层方法,调用SQL。
这对编写SQL的xml文件提出以下硬性要求:

  • namespace:必须和接口的全类名一致
  • sql的id:必须和对应的方法名一致
  • select标签中,返回值类型和参数类型也必须和对应的方法一致

4.1 编写Dao层接口

Dao层接口在myba中相关称之为Mapper。

public interface EmployeeMapper
{
    //根据id查询员工
    Employee getEmpById(Integer id);

    //根据id删除员工信息
    void  deleteEmpById(Integer id);
	//新增员工信息
    void insertEmp(Employee employee);
	//修改员工信息
    void updateEmp(Employee employee);
	//查询所有
    List<Employee> getAll();

4.2 编写Mapper所使用的SQL(EmployeeMapper.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--
   namespace:  名称空间,类似包名。
        必须和对应的接口的全类名一致
-->
<mapper namespace="com.atguigu.mybatis.mapper.EmployeeMapper">
    <!--
        定义sql,是什么语句,就用什么标签。
            select语句,使用 <select>标签

            语句标签上的id,是这条语句在这个文件中的唯一标识,必须保证唯一。
                要和对应的方法名一致!

            如果是查询语句,必须在标签头上声明返回值类型
                resultType: 查询的结果集中的一行要封装为的Bean的类型
    -->
   <!--
     字面量(字面上就能看出变量值的变量): 基本数据类型及包装类,String
        int a = 1;
        double b = 2.0d;
        String s = "haha";

        非字面量:  Employee e = new Employee();

      关于占位符:
            在jdbc中,使用?作为占位符
            在mybatis中,使用 #{xxx}作为占位符
                xxx:
                    如果传参的方法中,传入的参数中只有一个且是普通参数(字面量),xxx可以随便写.
                    如果传参的方法中,传入的参数中只有一个且是Bean,xxx可以写Bean的属性名,#{xxx}就能获取Bean的属性值。

   -->
    <select id="getEmpById" resultType="com.atguigu.mybatis.beans.Employee">
        <include refid="sql1"/> where id = #{id}
    </select>

    <!--
         void updateEmp(new Employee(1, "jack", "a", "b"));

         #{id} = 1
         #{lastName} = jack
    -->
    <update id="updateEmp">
        update employee set last_name = #{lastName} , gender = #{gender} ,email = #{email}
        where id = #{id}
    </update>

    <insert id="insertEmp">
        insert into employee(last_name,gender,email) values(#{lastName},#{gender},#{email})
    </insert>

    <delete id="deleteEmpById">
        delete from employee where id = #{xxxx}
    </delete>
	 <select id="getAllEmp" resultMap="rm1">
        select * from employee
    </select>
</mapper>

编写完之后要在全局的配置文件中注册

<mappers>
       <mapper resource="EmployeeMapper.xml"/>
</mappers>

4.3 接口式编程的使用步骤

SqlSession session = sqlSessionFactory.openSession();
        
        try {
       //获取接口的实现
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);

            //进行CRUD
            
        } finally {
            session.close();
        }

SqlSession由于不是线程安全的,因此不能作为静态变量或实例变量,而应该在每个方法中单独获取,并且使用完成之后关闭。不可以在多个方法中共享sqlSession!!!

4.4 测试代码

public class EmployeeMapperTest
{
    private SqlSessionFactory sqlSessionFactory;

    {
        String resource = "mybatis.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void getAll() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            //com.sun.proxy.$Proxy5 implements com.atguigu.mybatis.mapper.EmployeeMapper
            //使用Mybatis提供的动态代理技术,获取接口的一个实例
            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            //class com.sun.proxy.$Proxy5
            System.out.println(mapper.getClass());
            //[interface com.atguigu.mybatis.mapper.EmployeeMapper]
            System.out.println(Arrays.toString(mapper.getClass().getInterfaces()));
            //进行CRUD
            mapper.getAll().forEach(System.out::println);

        } finally {
            session.close();
        }
    }
@Test
    public void selectOne() {
        SqlSession session = sqlSessionFactory.openSession();

        try {

            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            //CRUD
            Employee emp = mapper.getEmpById(1);

            System.out.println(emp);

        } finally {
            session.close();
        }
    }
 @Test
    public void delete() {
        SqlSession session = sqlSessionFactory.openSession(true);

        try {

            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            //CRUD
            mapper.deleteEmpById(1);
             System.out.println("删除成功");
            //手动提交事务
            //session.commit();
        } finally {
            session.close();
        }
    }

    @Test
    public void update() {
        SqlSession session = sqlSessionFactory.openSession(true);

        try {

            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            //CRUD
            Employee e = mapper.getEmpById(3);
            e.setLastName("hahaha");
            e.setEmail("xixixi");
            mapper.updateEmp(e);
        } finally {
            session.close();
        }
    }

    @Test
    public void insert() {
        SqlSession session = sqlSessionFactory.openSession(true);

        try {

            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
            //CRUD
            mapper.insertEmp(new Employee(null, "jack", "a", "b"));
        } finally {
            session.close();
        }
    }
}

1、获取所有员工测试截图
在这里插入图片描述
2、根据id获取员工信息
在这里插入图片描述
3、根据id删除员工
在这里插入图片描述
4、更新员工信息
在这里插入图片描述
5、插入员工信息
在这里插入图片描述

4.5 注解接口式编程

如果注重效率,也可以直接在Mapper的方法上标注相应的注解从而替代mapper.xml
的效果。

public interface EmployeeMapper2
{
    //根据id查询员工
    @Select(" select * from employee where id = #{ageakljga} ")
    Employee getEmpById(Integer id);

    //增删改 写操作 不需要返回值
    @Delete("delete from employee where id = #{xxxx}")
    void  deleteEmpById(Integer id);

    @Insert("        insert into employee(last_name,gender,email) values(#{lastName},#{gender},#{email})\n")
    void insertEmp(Employee employee);

    @Update(" update employee set last_name = #{lastName} , gender = #{gender} ,email = #{email}\n" +
        "        where id = #{id}")
    void updateEmp(Employee employee);

    @Select(" select * from employee ")
    List<Employee> getAll();

}

添加注解之后,同样需要再全局配置文件中,配置sql语句所在的Mapper接口全类名

<mapper class="com.atguigu.mybatis.mapper.EmployeeMapper2"/>

5、ResultMap

当要封装的Bean的属性名和查询的方法无法一样对应时,就需要使用resultMap来自定义列名和Bean中字段的映射规则。
例如有如下查询方法

List<Emp> getAllEmp();

其中查询的Bean结构如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp
{
    private Integer id;
    private String name;
    private GenderAndEmail genderAndEmail;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GenderAndEmail
{
    private String gender;
    private String emailAddr;
}

此时Bean的字段名与所查询表的相关列名有很大差别。使用resultType直接封装的话,有很多字段是无法正常封装的。我们使用resultMap自定义映射规则。

 <select id="getAllEmp" resultMap="empMapRule">
        select *
        from employee
    </select>

<resultMap	id="empMapRule" type="com.atguigu.mybatis.beans.Emp" autoMapping="true">
            <result property="name" column="last_name"/>
            <association property="genderAndEmail" javaType="com.atguigu.mybatis.beans.GenderAndEmail" autoMapping="true">
                <result property="emailAddr" column="email"/>
            </association>
</resultMap>

6、引入Sql模板

在MySQL的Sql配置文件中,可以使用标签来定义sql,之后使用标签来引入sql,这样可以将高频使用的sql模板进行复用。
如下:

<select id="rowsOfTable" resultType="int">
            select count(*)
            <include refid="sql1"/>
</select>

<sql id="sql1">
       from employee
</sql>

7、获取接口方法入参

在sql的xml中,可以使用${}和#{}来获取方法中传入的参数。
${参数名}可以直接获取指定参数名的值,不做任何处理 (一般用与表名传参)
#{ 参数名}在获取指定参数后,还会对类型进行判断,进行相应的处理,例如为String类型的参数自动添加引号(一般用于参数传参)。
在使用@Param注解可以在接口方法有多个参数时,为参数自定义参数名。

8、Sql注入

sql注入通常指的是恶意利用sql语句拼接的漏洞,注入非法的查询条件,来非正常获取数据的行为。例如:

@Select("select * from employee where gender = ${gender}")
List<Employee> getEmpsByCondition(@Param("gender") String gender);

此时,在调用时,模拟sql注入如下:

List<Employee> emps = mapper.getEmpsByCondition("'male' or id > 0 ");

后果是,数据库中的所有用户信息都将被非法获取。所以在参数位置,我们要尽量避免使用${}而使用#{}

9、动态SQL

有时候,我们需要根据前台传入的参数动态的去拼接sql的过滤条件,如果使用${}去拼接sql,又会面临着sql注入的风险。所以,此时,可以使用MyBatis的动态sql技术,既可以满足拼接sql的需求,又可以避免sqk注入的风险。
示例:

List<Employee> queryByCondition(@Param("name") String name,
                                    @Param("id") Integer id, 
@Param("gender") String gender);

sql语句如下:

<select id="queryByCondition" resultType="com.zhm.mybatisplusdemo.beans.Employee">
        select
            *
        from emp
        <where>
            <if test=" name != null ">
                and last_name = #{name}
            </if>
            <if test=" id != null ">
                and id = #{id}
            </if>
            <if test=" gender != null ">
                and gender = #{gender}
            </if>
        </where>
</select>

其中标签可以在sql中直接生成一个where子句的标识符,还可以将where中不符合语法规则部分多余的and或or自动去除。但是需要注意的是,必须把and和or编写在语句的前列。
测试观察生成的sql:

mapper.queryByCondition(null,null,"a"))

在这里插入图片描述
                      您的支持是我创作的无限动力

在这里插入图片描述
                      希望我能为您的未来尽绵薄之力

在这里插入图片描述
                      如有错误,谢谢指正;若有收获,谢谢赞美

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

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

相关文章

什么是安全测试报告,怎么获得软件安全检测报告?

安全测试报告 软件安全测试报告&#xff1a;是指测试人员对软件产品的安全缺陷和非法入侵防范能力进行检查和验证的过程&#xff0c;并对软件安全质量进行整体评估&#xff0c;发现软件的缺陷与 bug&#xff0c;为开发人员修复漏洞、提高软件质量奠定坚实的基础。 怎么获得靠谱…

Hadoop学习一(初识大数据)

目录 一 什么是大数据&#xff1f; 二 大数据特征 三 分布式计算 四 Hadoop是什么? 五 Hadoop发展及版本 六 为什么要使用Hadoop 七 Hadoop vs. RDBMS 八 Hadoop生态圈 九 Hadoop架构 一 什么是大数据&#xff1f; 大数据是指无法在一定时间内用常规软件工具对其内…

昌硕科技、世硕电子同步上线法大大电子合同

近日&#xff0c;世界500强企业和硕联合旗下上海昌硕科技有限公司&#xff08;以下简称“昌硕科技”&#xff09;、世硕电子&#xff08;昆山&#xff09;有限公司&#xff08;以下简称“世硕电子”&#xff09;的电子签项目正式上线。上线仪式在上海浦东和硕集团科研大楼举行&…

渗透测试方法论

文章目录 渗透测试方法论1. 渗透测试种类黑盒测试白盒测试脆弱性评估 2. 安全测试方法论2.1 OWASP TOP 102.3 CWE2.4 CVE 3. 渗透测试流程3.1 通用渗透测试框架3.1.1 范围界定3.1.2 信息搜集3.1.3 目标识别3.1.4 服务枚举3.1.5 漏洞映射3.1.6 社会工程学3.1.7 漏洞利用3.1.8 权…

Java课题笔记~ SpringBoot基础配置

二、基础配置 1. 配置文件格式 问题导入 框架常见的配置文件有哪几种形式&#xff1f; 1.1 修改服务器端口 http://localhost:8080/books/1 >>> http://localhost/books/1 SpringBoot提供了多种属性配置方式 application.properties server.port80 applicati…

jmeter HTTP请求默认值

首先&#xff0c;打开JMeter并创建一个新的测试计划。 右键单击测试计划&#xff0c;选择"添加" > “配置元件” > “HTTP请求默认值”。 在HTTP请求默认值中&#xff0c;您可以设置全局的HTTP请求属性&#xff0c;例如&#xff1a; 服务器地址&#xff1a…

神经网络简单理解:机场登机

目录 神经网络简单理解&#xff1a;机场登机 ​编辑 激活函数&#xff1a;转为非线性问题 ​编辑 激活函数ReLU 通过神经元升维&#xff08;神经元数量&#xff09;&#xff1a;提升线性转化能力 通过增加隐藏层&#xff1a;增加非线性转化能力​编辑 模型越大&#xff0c;…

uniapp日期选择组件优化

<uni-forms-item label="出生年月" name="birthDate"><view style="display: flex;flex-direction: row;align-items: center;height: 100%;"><view class="" v-

【图论】最短路的传送问题

一.分层图问题&#xff08;单源传送&#xff09; &#xff08;1&#xff09;题目 P4568 [JLOI2011] 飞行路线 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) &#xff08;2&#xff09;思路 可知背景就是求最短路问题&#xff0c;但难点是可以使一条路距离缩短至0&#xf…

一、数学建模之线性规划篇

1.定义 2.例题 3.使用软件及解题 一、定义 1.线性规划&#xff08;Linear Programming&#xff0c;简称LP&#xff09;是一种数学优化技术&#xff0c;线性规划作为运筹学的一个重要分支&#xff0c;专门研究在给定一组线性约束条件下&#xff0c;如何找到一个最优的决策&…

绿盾客户端字体库文件被加密了,预览不了

环境: 绿盾客户端7.0 Win10 专业版 问题描述: 绿盾客户端字体库文件被加密了,预览不了 预览不了 解决方案 1.打开控制台 2.进入规则中心 3.找到对应的操作员类型 4.选择自定义程序 5.右键新建程序,填最开始获得的程序名,可执行程序选择本地程序,我本地没有这个…

pytest之parametrize参数化

前言 我们都知道pytest和unittest是兼容的&#xff0c;但是它也有不兼容的地方&#xff0c;比如ddt数据驱动&#xff0c;测试夹具fixtures&#xff08;即setup、teardown&#xff09;这些功能在pytest中都不能使用了&#xff0c;因为pytest已经不再继承unittest了。 不使用dd…

PHP8中自定义函数-PHP8知识详解

1、什么是函数&#xff1f; 函数&#xff0c;在英文中的单词是function&#xff0c;这个词语有功能的意思&#xff0c;也就是说&#xff0c;使用函数就是在编程的过程中&#xff0c;实现一定的功能。即函数就是实现一定功能的一段特定代码。 在前面的教学中&#xff0c;我们已…

如何进行在线pdf转ppt?在线pdf转ppt的方法

在当今数字化时代&#xff0c;PDF文件的广泛应用为我们的工作和学习带来了巨大的便利。然而&#xff0c;有时候我们可能需要将PDF转换为PPT文件&#xff0c;以便更好地展示和分享内容。在线PDF转PPT工具因其操作简便、高效而备受欢迎。如何进行在线pdf转ppt呢?接下来&#xff…

kafka--技术文档-基本概念-《快速了解kafka》

学习一种新的消息中间键&#xff0c;卡夫卡&#xff01;&#xff01;&#xff01; 官网网址 Apache Kafka 基本概念 Kafka是一种开源的分布式流处理平台&#xff0c;由Apache软件基金会开发&#xff0c;用Scala和Java编写。它是一个高吞吐量的分布式发布订阅消息系统&#xf…

c++ qt--信号与槽(二) (第四部分)

c qt–信号与槽(二) &#xff08;第四部分&#xff09; 一.信号与槽的关系 1.一对一 2.一对多 3.多对一 4.多对多 还可以进行传递 信号->信号->槽 一个信号控制多个槽的例子&#xff08;通过水平滑块控制两个组件&#xff09; 1.应用的组件 注意这里最下面的组件…

(五)Docker 安装 redis镜像+启动redis容器(超详细)

输入&#xff1a;su root命令&#xff0c;切换到root 1、启动Docker 启动&#xff1a;sudo systemctl start docker 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 查看docker运行状态&#xff08;显示绿色代表正常启动&#xff09;&#x…

WPF 项目中 MVVM模式 的简单例子说明

一、概述 MVVM 是 Model view viewModel 的简写。MVVM模式有助于将应用程序的业务和表示逻辑与用户界面清晰分离。 几个概念的说明&#xff1a; model :数据&#xff0c;界面中需要的数据&#xff0c;最好不要加逻辑代码view : 视图就是用户看到的UI结构 xaml 文件viewModel …

【STM32RT-Thread零基础入门】 6. 线程创建应用(线程挂起与恢复)

硬件&#xff1a;STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、RT-Thread相关接口函数1. 挂起线程2. 恢复线程 二、程序设计1. car_led.c2.car_led.h3. main.c 三、程序测试总结 前言 在上一个任务中&a…

【QML】鼠标放在控件上颜色改变的效果实现

最近刚好要用到一个功能&#xff0c;在qml上实现鼠标放上去&#xff0c;控件的颜色改变&#xff0c;鼠标移走&#xff0c;控件颜色恢复。第一反应是这个功能非常简单&#xff0c;但是搞了一会儿都没实现&#xff0c;最后发现MouseArea其实提供了一个很简便的方法来提供使用&…