Mybatis(搭建,CRUD,方法参数,XML映射文件,动态SQL)【详解】

目录

一.准备基础代码

Mybatis的通用配置

二. 基本CURD操作

1.查询-根据id查询一条

2.查询-查询数量

3.删除

4.新增

获取主键值

5.修改

6.查询-模糊查询

预编译SQL

#{}与${}的区别【面试题】

三. Mybatis的方法参数与结果集

1.SQL里取方法参数的值

2.查询结果集的封装

方案一:SQL语句里给字段起别名

方案二:使用@Results和@Result手动映射

四.Mybatis的XML映射文件

1.介绍

2.用法

3.示例

4.给idea配置代码模板

五、Mybatis的动态SQL【重点】

1. 动态SQL介绍

2. if标签和where标签

3. set标签

4. foreach标签

5. sql标签和include标签


一.准备基础代码

把基础工程《资料\00.基础工程\web09-mybatis-curd》拷贝到不含中文、空格、特殊字符的目录里,然后使用idea直接open打开项目

准备基础环境

  • 依赖pom.xml

<properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version></parent><dependencies><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

配置文件application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db4
spring.datasource.username=root
spring.datasource.password=root

引导类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MybatisCurdApplication {public static void main(String[] args) {SpringApplication.run(MybatisCurdApplication.class, args);}
}

查询所有员工

  • 实体类

import lombok.Data;import java.time.LocalDate;
import java.time.LocalDateTime;@Data
public class Emp {private Integer id;private String username;private String password;private String name;private Integer gender;private String image;private Integer job;private LocalDate entrydate;private Integer deptId;private LocalDateTime createTime;private LocalDateTime updateTime;
}

EmpMapper

import com.itheima.pojo.Emp;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface EmpMapper {@Select("select * from emp")List<Emp> queryAll();
}

功能测试

import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
public class CurdTest {@Autowiredprivate EmpMapper empMapper;@Testpublic void testQueryAll(){List<Emp> emps = empMapper.queryAll();emps.forEach(System.out::println);}
}

Mybatis的通用配置

Mybatis的日志输出

直接修改application.properties,增加配置:

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

Mybatis下划线与驼峰命名转换

直接修改application.properties,增加配置:

#开启下划线与驼峰命名的自动映射。
# 如果设置为true,那么数据库里下划线命名风格的字段,会自动映射到Java里驼峰式命名的属性
# 比如:数据库字段是dept_id, Java里的成员变量名是deptId。 Mybatis会认为这两个是对应的
mybatis.configuration.map-underscore-to-camel-case=true

基本CURD操作

使用Mybatis,无论什么功能,都只需要:

  • 在Mapper接口里写一个方法

  • 给方法配置SQL语句:用注解

二. 基本CURD操作

1.查询-根据id查询一条

EmpMapper:实现功能

/*** 0. 先准备好SQL语句* 1. 方法的参数:根据SQL语句需要的参数来定*      这些参数都是给SQL语句使用。SQL语句里需要几个参数,方法上就要加几个形参*      SQL语句里要获取参数值,如果方法只有一个参数,写法是:#{随意写},建议写成#{参数名}* 2. 方法的返回值:根据我们想要得到什么结果来定*      我们期望Mybatis帮我们把查询结果封装成什么对象。*      写成Emp,Mybatis就会把查询的结果封装成一个Emp对象*      注意:实体类里的属性名,要和表的字段名 一致(相同,或者符合下划与驼峰命名的规则)*/
@Select("select * from emp where id = #{id}")
Emp queryById(Integer id);

CurdTest:功能测试

@Test
public void testQueryById(){Emp emp = empMapper.queryById(1);System.out.println("emp = " + emp);
}

2.查询-查询数量

EmpMapper:实现功能

/*** 查询数量:SQL语句 select count(*) from emp* 方法要参数吗?不需要。因为SQL语句不需要参数* 方法返回值是什么类型?能够封装查询结果即可,可使用int、long*/
@Select("select count(*) from emp")
int queryCount();

CurdTest:功能测试

@Test
public void testQueryCount(){int count = empMapper.queryCount();System.out.println("count = " + count);
}

3.删除

EmpMapper:实现功能

/*** 根据id删除一个员工:delete from emp where id = ?* 配置查询语句:@Select* 配置新增语句:@Insert* 配置修改语句:@Update* 配置删除语句:@Delete*/
@Delete("delete from emp where id = #{id}")
void deleteById(Integer id);

CurdTest:功能测试

@Test
public void testDeleteById(){empMapper.deleteById(17);
}

4.新增

EmpMapper:实现功能

/*** 插入一条员工数据:* INSERT INTO emp (id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)* VALUES (16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, '2023-08-19 10:39:37', '2023-08-19 10:39:37');** 方法的参数:*      如果SQL语句需要的参数过多,方法的形参可以使用一个实体类*      SQL语句里使用 #{JavaBean的属性名}*      注意:*          不要写成 '#{JavaBean属性名}'*          #{属性名}的顺序,必须与前边的字段顺序是一致对应的*/
@Insert("INSERT INTO emp (username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +"VALUES (#{username}, #{password}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
void insert(Emp emp);

CurdTest:功能测试

@Test
public void testInsert(){Emp emp = new Emp();emp.setUsername("tom");emp.setPassword("123");emp.setName("汤姆");emp.setGender(1);emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());empMapper.insert(emp);
}
获取主键值

如果执行insert时,需要获取数据的主键值,我们可以做:

  • 在Mapper接口里插入的方法上,再增加注解:@Options(useGeneratedKeys=true, keyProperty="JavaBean里的属性名")

/*** 插入一条员工数据:* INSERT INTO emp (id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)* VALUES (16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, '2023-08-19 10:39:37', '2023-08-19 10:39:37');** 方法的参数:*      如果SQL语句需要的参数过多,方法的形参可以使用一个实体类*      SQL语句里使用 #{JavaBean的属性名}*      注意:*          不要写成 '#{JavaBean属性名}'*          #{属性名}的顺序,必须与前边的字段顺序是一致对应的* 如果插入数据之后,需要获取数据的主键值:@Options*      useGeneratedKeys:利用数据库的主键自增得到主键值*      keyProperty:把得到的主键值,存储到参数实体类对象的哪个属性上*/@Options(useGeneratedKeys = true, keyProperty = "id")@Insert("INSERT INTO emp (username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +"VALUES (#{username}, #{password}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")void insert(Emp emp);

5.修改

EmpMapper:实现功能

/*** 修改id为19的数据:* UPDATE emp SET username = 'jerry', password = '123', name = '杰瑞', gender = 1, image = null, job = null, entrydate = null, dept_id = null, create_time = '2023-08-19 14:54:29', update_time = '2023-08-19 14:54:29' WHERE id = 19;*/
@Update("UPDATE emp SET username = #{username}, password = #{password}, name = #{name}, gender = #{gender}, image = #{image}, job = #{job}, " +"entrydate = #{entrydate}, dept_id = #{deptId}, create_time = #{createTime}, update_time = #{updateTime} WHERE id = #{id}")
void updateById(Emp emp);

CurdTest:功能测试

@Test
public void testUpdateById(){Emp emp = empMapper.queryById(19);emp.setUsername("robin li");emp.setGender(2);empMapper.updateById(emp);
}

6.查询-模糊查询

EmpMapper:实现功能

/*** 模糊查询:查询姓名里包含“张”的员工列表* select * from emp where name like '%张%';* SQL语句里拼接字符串函数:concat(字符串1, 字符串2, 字符串3,....)*/@Select("select * from emp where name like concat('%', #{name}, '%')")List<Emp> queryByName1(String name);@Select("select * from emp where name like '%${name}%'")List<Emp> queryByName2(String name);

CurdTest:功能测试

  @Testpublic void testQueryByName1(){List<Emp> list = empMapper.queryByName1("张");list.forEach(System.out::println);}@Testpublic void testQueryByName2(){List<Emp> list = empMapper.queryByName2("张");list.forEach(System.out::println);}
预编译SQL

预编译:不是Mybatis的概念,而是JDBC的概念。

  • 不使用预编译:RDBMS先编译SQL(解析SQL语句,确定SQL的执行方案);再执行SQL语句,得到结果

  • 使用了预编译:先把SQL语句进行解析确定执行方案;然后设置参数值执行SQL

好处1-预编译执行SQL性能更高

好处2-可以防止SQL注入漏洞

#{}${}的区别【面试题】
  • #{}:底层使用的是预编译方式。

    更安全,因为可以防止SQL注入漏洞

    执行SQL的性能更高

  • ${}:没有使用预编译,是直接拼接SQL字符串

    不安全,可能存在SQL注入漏洞

    执行SQL的性能不如预编译

三. Mybatis的方法参数与结果集

1.SQL里取方法参数的值

如果方法只有一个参数:

  • 如果参数是简单值(8种基本数据类型及包装类、String),SQL语句里取参数值是:#{参数名}

  • 如果参数是JavaBean对象,SQL语句里取JavaBean的属性值:#{属性名}

如果方法有多个参数,SQL语句里取参数值:

  • 从SpringBoot2版本开始:#{形参名}

  • 在SpringBoot2以前版本:【了解】

    首先,给方法参数起名称,添加注解:@Param("名称")

    然后,在SQL语句里使用:#{名称} 获取对应参数值

/*** 需求:根据姓名、性别、入职时间范围 搜索员工信息* SQL:select * from emp where name like ? and gender = ? and entrydate between ? and ?* 如果方法有多个参数,SQL语句里取参数值:#{参数名称}。从SpringBoot2开始提供的功能*/
@Select("select * from emp where name like concat('%',#{name}, '%') and gender = #{gender} and entrydate between #{begin} and #{end}")
List<Emp> queryEmpList(String name,Integer gender,LocalDate begin,LocalDate end);@Select("select * from emp where name like concat('%',#{a}, '%') and gender = #{b} " +"and entrydate between #{c} and #{d}")
List<Emp> queryEmpList2(@Param("a") String name,@Param("b") Integer gender,@Param("c") LocalDate begin,@Param("d") LocalDate end);

2.查询结果集的封装

Mybatis会自动帮我们把查询的结果集封装成实体类对象,前提条件是:

  • 要么 JavaBean的属性名,和 表的字段名完全相同。

    比如:字段名是gender,Emp类里的属性名也叫gender

  • 要么 JavaBean的属性名,和 表的字段名按照 下划线与驼峰映射 是一致的。

    比如:字段名是dept_id,Emp类里属性名是deptId

    前提:开启下划线与驼峰的命名转换,修改application.properties配置文件,添加参数

    mybatis.configuration.map-underscore-to-camel-case=true

如果JavaBean的属性名和字段名完全不匹配,就需要处理这种情况

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {private Integer id;/*对应的字段名是username*/private String uname;/*对应的字段名是password*/private String pword;private String name;private Integer gender;private String image;private Integer job;private LocalDate entrydate;private Integer deptId;private LocalDateTime createTime;private LocalDateTime updateTime;
}
方案一:SQL语句里给字段起别名
/*** JavaBean属性名 与  表字段名 完全不匹配:* SQL语句里给字段起别名,别名和JavaBean属性名相同*/
@Select("select id, username as uname, password as pword,name,gender,image,job," +"entrydate,dept_id,create_time, update_time from emp")
List<Employee> queryEmployeeList2();
方案二:使用@Results@Result手动映射

只需要把不同的字段配置一下,如果字段和属性名匹配,就不需要做配置

/*** JavaBean属性名 与  表字段名 完全不匹配:* 我们使用@Results和@Result注解,手动设置一下,哪个字段对应哪个属性*      注解1:@Results,用于配置当前查询里所有字段的映射关系*      注解2:@Result,用于配置某一个字段与属性的对应关系*          property:写的是JavaBean的属性名*          column:写的是表里的字段名*/
@Select("select * from emp")
@Results({@Result(property = "uname", column = "username"),@Result(property = "pword", column = "password")
})
List<Employee> queryEmployeeList3();

四.Mybatis的XML映射文件

1.介绍

Mybatis的SQL语句,可以使用注解直接配置到Mapper接口里的方法上,也可以定义到XML文件里

  • 如果SQL语句写到接口里的方法上:注解方式,适合于简单SQL或者固定不变的SQL

  • 如果SQL语句写到XML文件里:xml方式,更适合于复杂SQL或者动态变化的SQL

注意:XML方式和注解方式可以同时使用,但是要注意

  • 一个方法的SQL语句,要么用注解方式配置,要么用XML方式配置,不能重复配置

2.用法

XML文件的要求:

  1. XML文件的位置:要和Mapper同一包下,按照maven规范,要放到resources里边的同名文件夹下

  2. XML文件的名称:要和Mapper接口的名称相同

XML内容的要求:

  • 根标签<mapper namespace="Mapper接口的全限定类名">:表示当前XML是给哪个Mapper接口配置语句的

  • 在mapper标签里边,配置SQL语句:

    • select标签:配置select语句,SQL语句写到标签里边。需要配置id属性和resultType属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

      • resultType属性:告诉Mybatis要把查询结果中的每一行数据,封装成什么对象

    • insert标签:配置insert语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

    • update标签:配置update语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

    • delete标签:配置delete语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

3.示例

Mapper接口

/*** 使用XML方式配置SQL语句* XML文件的位置:Mapper接口在什么包,XML文件就必须在同包下。*      在resources目录下右键,创建Directory文件夹,以/为分隔符,千万不要以.为分隔符。*      比如:com/itheima/mapper* XML文件的名称:Mapper接口叫什么名字,XML文件也叫什么名字**/
List<Emp> queryEmpListXml(String name,Integer gender,LocalDate begin,LocalDate end);

XML映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper标签:根标签namespace:要写Mapper接口的全限定类名。表示当前xml文件,是给哪个Mapper接口配置的
mapper的子标签:select标签:配置select语句,SQL语句写到标签里边insert标签:配置insert语句,SQL语句写到标签里边update标签:配置update语句,SQL语句写到标签里边delete标签:配置delete语句,SQL语句写到标签里边以上标签都有的属性:id:写方法名。表示当前语句是给哪个方法配置的resultType:select标签专用的属性用于告诉Mybatis,SQL查询语句的结果,要封装成什么对象写JavaBean的全限定类名,不需要写List、Set等等
-->
<mapper namespace="com.itheima.mapper.EmpMapper"><select id="queryEmpListXml" resultType="com.itheima.pojo.Emp">select * from empwhere name like concat('%',#{name}, '%')and gender = #{gender}and entrydate between #{begin} and #{end}</select>
</mapper>

功能测试

@Test
public void testQueryEmpListXml(){LocalDate begin = LocalDate.of(2010, 1, 1);LocalDate end = LocalDate.of(2015, 12, 31);List<Emp> emps = empMapper.queryEmpListXml("张", 1, begin, end);for (Emp emp : emps) {System.out.println("emp = " + emp);}
}

4.给idea配置代码模板

配置方式:File | Settings | Editor | Live Templates

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

五、Mybatis的动态SQL【重点】

1. 动态SQL介绍

当进行多条件搜索时,搜索条件通常是不确定的,导致SQL语句的条件也是不确定的:需要根据条件,来确定要拼接哪些查询条件。这样的SQL语句,就是所谓的动态SQL

Mybatis提供了一些xml的标签,用于实现动态SQL语句:

  • if标签:用于判断

    • where标签:用于代替where关键字

    • set标签:用于代替set关键字

  • foreach标签:用于循环遍历

  • sql标签和include标签:用于抽取重用sql片段

2. if标签和where标签

if标签:用于进行判断。如果判断为true,标签里的sql才会生效

<if test="判断条件">
    如果判断为true,这里的内容才会生效
</if>

where标签:用于代替where关键字,它可以帮我们处理多余的and和or,还有处理我们的空集合,不是null

演示:

Mapper接口

     /*** 动态SQL:根据条件查询员工。根据name和gender动态查询*/List<Emp> searchEmp1(String name, Integer gender);

XML映射

<!--if标签:用于判断语法:<if test="判断条件表达式">如果判断为true,这里的内容将会生效</if>判断条件表达式:其实使用的是OGNL的表达式语法:名称,取对应参数的值。#{}是怎么取参数值的,这里也怎么取参数值判断运算:>, <, >=, <=, ==, !=逻辑运算:&&, ||, ! 或者 and or not调用参数的属性或者方法where标签:用于代替where关键字还会帮我们处理掉SQL语句里多余的and关键字使用了where标签之后,建议给所有的条件前边都加上and--><select id="searchEmp1" resultType="com.itheima.pojo.Emp">select * from emp<where><!-- 如果参数name值非空 并且不是空串,就添加上name的条件--><if test="name!=null and name.length()>0">and name like concat('%',#{name}, '%')</if><!-- 如果参数gender非空,就添加上gender的条件 --><if test="gender!=null">and gender = #{gender}</if></where></select>

3. set标签

set标签:用于代替update语句里的set关键字,可以帮我们处理多余的逗号

Mapper

void update(Emp emp);

XML映射

<!--
set标签:用于代替update语句里的set关键字可以帮我们处理掉多余的,逗号把所有要修改的字段sql片段,都写到set标签里边
-->
<update id="update">update emp<set><if test="username!=null and username.length()>0">username=#{username},</if><if test="password!=null and password.length()>0">password= #{password},</if><if test="name!=null and name.length()>0">name= #{name},</if><if test="gender!=null">gender= #{gender},</if><if test="image!=null and image.length()>0">image= #{image},</if><if test="entrydate!=null">entrydate= #{entrydate},</if><if test="deptId!=null">dept_id= #{deptId},</if><if test="updateTime!=null">update_time= #{updateTime}</if></set>where id = #{id}
</update>

4. foreach标签

foreach标签:用于循环遍历,比如我们的批量删除,多个数据

Mapper

void batchDelete(List<Integer> ids);

XML映射

<!--
foreach标签:collection:被循环的集合或数组item:定义一个变量名,通过这个变量名可以获取集合或数组里的每个值separator:拼接每个值时候,使用的分隔符open:拼接结果的前缀部分close:拼接结果的后缀部分
假如:ids值是 1,2,3
循环拼接的结果是:delete from emp where id in (1,2,3)(1,2,3)
for(Integer id:ids){}
-->
<delete id="batchDelete">delete from emp where<foreach collection="ids" open="id in(" item="id" separator="," close=")">#{id}</foreach>
</delete>

5. sql标签和include标签

sql标签:定义一个sql片段

include标签:引用一个sql片段

用法 :如果多条SQL语句里,有某些片段是完全相同的,可以使用sql标签抽取出去,需要使用时用include引用即可

<!--定义一个SQL片段-->
<sql id="selectEmp">select * from emp</sql><!-- 引用一个SQL片段 -->
<select id="queryEmpListXml" resultType="com.itheima.pojo.Emp"><!--利用include标签,引用:select * from emp--><include refid="selectEmp"></include>where name like concat('%',#{name}, '%')and gender = #{gender}and entrydate between #{begin} and #{end}
</select>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

固定资产管理系统:井然有序,提升利用率,降损增值的解决之道。

固定资产管理系统是一种用于管理和跟踪组织内固定资产的软件系统。固定资产是指组织长期持有并用于生产、运营或提供服务的资产&#xff0c;例如土地、建筑物、机器设备、车辆等。 固定资产管理系统提供了一种集中管理和监控固定资产的方式&#xff0c;帮助组织更好地管理其资产…

人工智能 安装GPU环境 windows版

准备工作 需要有NVIDIA账号 磁盘要有50G 空间 我这里是 aws的 G4dn 虚拟机, 对应的 Tesla显卡,操作系统windows2022 1,安装VS 用社区版2019即可 https://my.visualstudio.com/Downloads?PId8228 2,下载完后运行程序选择C桌面版 大概5-10个G 3,下载完后运行一下 有账号就输…

房天下登录接口JS逆向

声明 本文章中所有内容仅供学习交流&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 逆向目标 目标&#xff1a;房天下账号密码登录 主页&#xff1a;https://passport.…

HarmonyOS NEXT应用开发—自定义日历选择器

介绍 本示例介绍通过CustomDialogController类显示自定义日历选择器。 效果图预览 使用说明 加载完成后显示主界面&#xff0c;点当前日期后会弹出日历选择器&#xff0c;选择日期后会关闭弹窗&#xff0c;主页面日期会变成选定的日期。 实现思路 获取当前月和下个月的日期…

WIFI 7技术的应用前景

随着WIFI 7技术的不断成熟和普及&#xff08;如果对WIFI 7技术不太了解的&#xff0c;可以点击链接去查看一下这篇文章WIFI7&#xff1a;开启无线通信新纪元 &#xff09;&#xff0c;我们正迎来一个数字连接的全新时代。WIFI 7作为新一代无线网络标准&#xff0c;将极大的改变…

Selenium 是什么?简单了解Selenium

Selenium Selenium 是什么 Selenium 是一款 Web UI 测试工具&#xff0c;是一款 自动化测试 工具&#xff0c;使用 Selenium 测试工具进行的测试通常被称为 Selenium Testing&#xff0c;各种支持如下列表&#xff1a; UI 元素的支持与管理&#xff1a;自写代码实现浏览器支…

【Qt】用Qt开发需要购买授权吗?——关于(L)GPL证书的详解

目录 Qt证书体系开源证书解读Qt官方对(L)GPL的描述自由度要求 GPL vs. LGPL完整条款 总结参考 Qt证书体系 你在用Qt开发应用的过程中&#xff0c;是否也担心过授权问题&#xff1f; 按照官方说法 The Qt framework is dual-licensed, available under both commercial and op…

Leetcode 3.15

Leetcode hot100 二叉树1.二叉搜索树中第K小的元素2.二叉树展开为链表3.从前序与中序遍历序列构造二叉树 二叉树 1.二叉搜索树中第K小的元素 二叉搜索树中第K小的元素 最重要的知识点&#xff1a;二叉树搜索树的中序遍历是升序的。 方法一&#xff1a;我们只需存储升序遍历&…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:ListItemGroup)

该组件用来展示列表item分组&#xff0c;宽度默认充满List组件&#xff0c;必须配合List组件来使用。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。该组件的父组件只能是List。 使用说明 当List…

Docker使用(四)Docker常见问题分析和解决收集整理

Docker使用(四)Docker常见问题分析和解决收集整理 五、常见问题 1、 启动异常 【描述】&#xff1a; 【分析】&#xff1a;[rootlocalhost ~]# systemctl status docker 【解决】&#xff1a; &#xff08;1&#xff09;卸载后重新安装&#xff0c;不能解决这个问题。 …

Android cmdline tools安装

打开AS 进入SDK Tools 看到了吗?那个打着勾的就是

如何将图片无损放大?

如何将图片无损放大&#xff1f; 在处理图片时&#xff0c;我们经常会遇到需要放大图像而又不损失图像质量的情况。这种操作被称为“图片无损放大”&#xff0c;它可以帮助我们保持图像的清晰度和细节&#xff0c;同时满足对更大尺寸图像的需求。传统的图像放大方法往往会导致…

重要表格比较多 不想被别人查阅 怎样批量加密?excel批量加密

批量给Excel工作表加密是一个既实用又具挑战性的任务。对于需要在多个工作表中保护敏感信息的用户来说&#xff0c;掌握这一技能尤为重要。下面&#xff0c;我们将详细介绍如何批量给Excel工作表加密 首先&#xff0c;我们要选择合适的加密方法&#xff0c;在这里小编给大家推荐…

Spring MVC(一)— DispatcherServlet

DispatcherServlet 是Spring MVC框架的HTTP 请求处理器的中央调度器。它具有以下的功能&#xff1a; 1&#xff09;基于IoC容器JavaBean配置机制。 2&#xff09;使用HandlerMappingl来实现请求到处理器的路由映射。 3&#xff09;使用HandlerAdapter 来处理不同的处理器。 …

【自动驾驶可视化工具】

自动驾驶可视化工具 自动驾驶可视化工具1.百度Apollo的Dreamview:2.Cruise的Worldview:3.Uber的AVS:4.Fglovex Studio: 自动驾驶可视化工具 介绍一下当前主流的自动驾驶可视化工具。 1.百度Apollo的Dreamview: Dreamview是百度Apollo平台开发的一种可视化工具&#xff0c;用…

使用Spark清洗统计业务数据并保存到数据库中

1、打开前面创建的项目“BigData-Etl-KongGuan”&#xff0c;创建一些数据库访问的工具类和辅助类。 1&#xff09;打开SpringBoot项目&#xff1a;BigData-Etl-KongGuan 2&#xff09;创建数据库访问的工具类和辅助类&#xff1a; com.qrsoft.etl.dao.IBaseDao数据库访问的通…

基于正点原子潘多拉STM32L496开发板的简易示波器

一、前言 由于需要对ADC采样性能的评估&#xff0c;重点在于对原波形的拟合性能。 考虑到数据的直观性&#xff0c;本来计划采集后使用串口导出&#xff0c;并用图形做数据拟合&#xff0c;但是这样做的效率低下&#xff0c;不符合实时观察的需要&#xff0c;于是将开发板的屏幕…

部署prometheus+Grafana可视化仪表盘监控服务

一、部署prometheus及监控仪表盘 简介 Prometheus是开源监控报警系统和时序列数据库(TSDB)。 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态&#xff0c;任意组件只要提供对应的HTTP接口就可以接入监控&#xff0c;输出被监控组件信息的HTTP接口被叫做expo…

Node.js(1)

跨平台的node.js运行环境&#xff0c;使开发者可以搭建服务器端的js应用程序 它可以编写服务器端程序&#xff1b; 编写数据接口&#xff1b;提供网页资源浏览功能 前端工程化&#xff1a;开发集成的所有工具和技术 与浏览器环境的区别 node.js环境中没有DOM和BOM fs模块-读…

5 个适用于 Windows 10 和 11 的最佳 PDF 转 Word 转换器

PDF 文件是共享文档的首选格式&#xff0c;但是此类文件存在一些限制&#xff0c;导致难以修改或编辑。因此&#xff0c;您可能会发现自己正在寻找一种将 PDF 文件转换为 Word 或其他可编辑格式的方法。 有许多不同的 PDF 转换器&#xff0c;每种转换器提供的功能略有不同。本…