当前位置: 首页 > news >正文

【MyBatis】快速入门MyBatis(保姆式教学),你值得一看

文章目录

  • 📄前言
  • 一. Mybatis简介
    • ✈️1. 什么是Mybatis
    • 🚀2. 为什么使用Mybatis
  • 二. Mybatis快速入门
    • 🍆1. mybatis使用前准备
      • 1.1 创建springboot项目并引入相关依赖
      • 1.2 在 application.ym中进行数据源的配置
      • 1.3 创建数据表,准备表数据
    • 🍅2. 使用注解的方式编写 SQL
      • 2.1 在mapper包下创建一个对应的 Mapper接口,并创建对应的实体类
      • 2.2声明接口方法(参数,返回值)
      • 2.3 在方法上加对应的注解并编写 sql
      • 2.4 使用 Alt + insert 生成测试类并执行测试方法
      • 获取主键
      • 解决结果映射问题
    • 🥦3. mybatis的其他配置
      • 3.1 mybatis的日志打印
      • 3.2 配置驼峰自动转换
    • 🍉4. 使用XML的方式编写 SQL
      • 4.1 在mapper包下创建一个对应的 Mapper接口,并创建对应的实体类
      • 4.2 声明接口方法(参数,返回值)
      • 4.3 创建 xml 文件进行映射配置并编写 sql
      • 4.4 使用 Alt + insert 生成测试类并执行测试方法
      • 获取主键
      • 解决结果映射问题
    • 🍋5. #{} 和 ${}
  • 三. 动态 SQL
    • 🍚if 标签
    • 🍥trim 标签
    • 🍭where 标签
    • 🍦set 标签
    • 🧊foreach 标签
    • 🍬sql 和 include 标签

📄前言

本文是对初学 mybatis的知识总结,希望我的内容能给你带来一定的帮助。

一. Mybatis简介

✈️1. 什么是Mybatis

以下是来自 MyBatis中文网 对MyBatis的介绍:

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

简单来说:Mybatis是一款用于日常开发中操作数据库的高级框架,它对 JDBC(传统用于访问关系型数据库的API)的操作进行了封装,使得数据库操作在Java程序变得更加简单和灵活,此外它还支持 关联查询和动态SQL等功能,极大提升了开发效率。

🚀2. 为什么使用Mybatis

为什么说 mybatis 是一款优秀的持久层框架呢?
原因其实很简单:简单,好用。我们可以回顾一下传统用于操作数据库的API——JDBC的使用步骤:

  1. 创建数据库连接池 DataSource
  2. 通过连接池 DataSource 获取数据库连接 Connection
  3. 编写带 ?占位符的SQL语句
  4. 通过Connection 和 SQL语句 创建PreparedStatement对象
  5. 通过PreparedStatement对象对 ?占位符逐一替换
  6. 执行SQL语句(查询操作或修改操作)
  7. 若执行查询操作,需要对返回的结果集对象(ResultSet)进行处理
  8. 释放资源(ResultSet,PreparedStatement和Connection等)

使用代码示例如下:

public static void main(String[] args) throws SQLException {// 1. 创建 DataSourceDataSource dataSource = new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("0000");// 2. 与数据库建立连接Connection connection = dataSource.getConnection();// 3. 构造sql语句并创建 PreparedStatement 对象String sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);// 4. 执行 sql ,接收返回的 ResultSet 对象ResultSet resultSet = statement.executeQuery();// 5. 遍历并处理结果集合,while(resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");System.out.println("id = " + id + ", name = " + name);}// 6. 释放资源,后获取到的资源先释放resultSet.close();statement.close();connection.close();
}

而使用Mybatis操作数据库步骤如下:

  1. 在application.yml 或 application.properties 配置文件中进行数据库的参数配置(整个程序只需配置一次,等同于创建数据库连接池DataSource)
  2. 进行访问数据库方法的定义
  3. 使用 注解或XML 的方式编写SQL语句
  4. 使用定义的方法执行SQL语句(查询操作或修改操作)
  5. 若为查询操作,只需使用集合接收查询结果,无需对结果集进行处理

使用代码示例如下:
在这里插入图片描述

@Select("select * from userinfo where id = #{id} and username = #{name}")
List<UserInfo> queryUserInfo(String name, Integer Id);

使用体验对比应该显而易见,使用Mybatis可以极大提高开发效率。


二. Mybatis快速入门

使用mybatis编写 sql 语句有 注解和XML两种方式,不管哪种方式都应该有一个接口来声明所要执行的 SQL 的方法,且一般这些持久层的代码都应放在mapper(dao)文件夹下。

在正式编写 sql 前我们需要进行一些准备工作。

🍆1. mybatis使用前准备

1.1 创建springboot项目并引入相关依赖

创建SpringBoot项目,在pom.xm文件中l引入mybatis相关依赖和mysql的驱动包(注意SpringBoot版本、JDK版本和 Mybatis相关依赖的版本要对应 )
在这里插入图片描述

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version>
</dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>

1.2 在 application.ym中进行数据源的配置

注意:在 application.properties中配置同理

# 数据库连接配置
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: xxxxxdriver-class-name: com.mysql.cj.jdbc.Driver

1.3 创建数据表,准备表数据

CREATE table stu(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(30) NOT NULL, age Int, gender VARCHAR(20),phone VARCHAR(30) NOT NULL);
INSERT INTO stu (name, age, gender, phone )
VALUES
( 'admin', 18, 1, '18612340001' ),
( 'zhangsan', 18, 1, '18612340002' ),
( 'lisi', 18, 1, '18612340003' ),
( 'wangwu', 18, 1, '18612340004' );

🍅2. 使用注解的方式编写 SQL

2.1 在mapper包下创建一个对应的 Mapper接口,并创建对应的实体类

注意:要在接口上加上@Mapper注解,这样我们编写接口才能被SpringBoot管理
在这里插入图片描述

package com.xuan.mybatis.model;import lombok.Data;@Data
public class Student {private Integer id;private String name;private Integer age;private String gender;private String phone;
}

2.2声明接口方法(参数,返回值)

注意:

  • 接口的形参过多时,可以根据需要创建一个实体类,用对象作为参数
  • 使用 select 从数据库查询记录时,通常使用对象或对象集合作为返回值,且对象的字段名与数据库的列名一一对应
package com.xuan.mybatis.mapper;
import com.xuan.mybatis.model.Student;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface StudentInfoMapper {// 查询操作List<Student> queryAllStudentInfo();// 新增操作Integer insert(String name, Integer age, String phone);// 删除操作Integer deleteUser (String name, String phone);// 修改操作Integer update(Student studentInfo);}

2.3 在方法上加对应的注解并编写 sql

注意:

  • @Select、@Insert、@Delete和@Update注解与 sql的增删改查的关键字作用是一样的,需在对应操作的方法上加上对应的注解
  • 如需构造带参数的 SQL语句,可以使用 #{} 作为占位符,他相当于 JDBC中 PreparedStatement 的 ?占位符,程序执行时会将方法中的参数放在 { } 中,即 #{参数}。
  • 使用对象作为方法参数构造的 SQL语句 同样只需使用 #{属性名} 作为参数。
package com.xuan.mybatis.mapper;
import com.xuan.mybatis.model.Student;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface StudentInfoMapper {// 查询操作@Select("select * from student")List<Student> queryAllStudentInfo();// 新增操作@Insert("insert into student (name, age, phone) values (#{name}, #{age}, #{phone})")Integer insert(String name, Integer age, String phone);// 删除操作@Delete("delete from student where name = #{name} or phone = #{phone}")Integer deleteUser (String name, String phone);// 修改操作(使用对象作为参数,需提供getter方法)@Update("update student set phone = #{phone} where name = #{name}")Integer update(Student studentInfo);}

2.4 使用 Alt + insert 生成测试类并执行测试方法

注意:需在测试类加上 @SpringBootTest注解,并使用@Autowired 注入 StudentInfoMapper属性)
在这里插入图片描述
编写并执行测试代码:

package com.xuan.mybatis.mapper;import com.xuan.mybatis.model.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class StudentInfoMapperTest {// 注入 StudentInfoMapper属性@Autowiredprivate StudentInfoMapper studentInfoMapper;@Testvoid queryAllUserInfo() {System.out.println(studentInfoMapper.queryAllUserInfo());;}@Testvoid insert() {studentInfoMapper.insert("zhaoliu", 16, "12345678900");}@Testvoid deleteUser() {studentInfoMapper.deleteUser("zhangsan", "18612340002");}@Testvoid update() {Student student = new Student();student.setName("admin");student.setPhone("00987654321");}
}

执行代码前:
在这里插入图片描述

执行代码后结果如下:
在这里插入图片描述
在这里插入图片描述

获取主键

在某些表中,我们通常设置 id 属性为表的自增主键,当我们在某次插入操作中想获取生成的 id 值该如何做呢?
答案是在方法上加上@Option注解: @Options(useGeneratedKeys = true, keyProperty = “id”)。
useGeneratedKeys = true 意思是将插入数据时自动生成的主键返回(默认值为 false);keyProperty = “id” 意思是将主键的值赋值给传入对象的 id属性。

接口和测试代码示例如下:

@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into student (name, age, phone) values (#{name}, #{age}, #{phone})")
Integer insert2(Student student);
@Test
void insert2() {Student student = new Student();student.setName("xiaoming");student.setAge(15);student.setPhone("123456");studentInfoMapper.insert2(student);System.out.println("id: " + student.getId());
}

返回结果如下:
在这里插入图片描述

解决结果映射问题

什么是结果映射问题呢?
数据库的表字段名与Java实体类对象的属性名不同时,通过 select查询语句 所得的结果集中,不同的字段会出现映射失败的现象,而且赋值为 null。(如下图所示)
在这里插入图片描述

为什么会出现结果映射问题?
最直接的原因是字段名称不一致,但本质是Java中属性的命名规范(小驼峰)和 Mysql中字段的命名规范(用 _ 作为分隔符)不同。

如何解决结果映射问题呢?

  1. 最直接的方法是在构造 SQL语句时 使用 as 给返回结果的列起别名。(不推荐,因为每个 sql 语句都需要进行同样的操作)
  2. 使用注解的方式给所有需要映射字段作说明(可行,但不是最佳的方式)
  3. 在 application.yml 文件中进行相关配置,将两种命名方式进行自动映射(后面再介绍)

那么如何采用注解对所需字段进行映射呢?
在接口上添加@Results注解。注解的使用示例如下:

@Results(id = "BaseResult", value = {@Result(column = "delete_flag", property = "deleteFlag"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")
})

其中 value = { } 是对所有映射关系的描述。
id = “BaseResult” 中 id 的值是为该映射结果集起名,作用是其他的接口也想使用这些映射, 可以在接口上添加 @ResultMap(value = “BaseResult”) 就可完成这个映射结果集的复用。
@Result(column = “delete_flag”, property = “deleteFlag”) 是对每个对应字段映射的描述,其中 column 的值是数据库的字段名property 的值是Java实体类的属性名

代码与程序运行结果示例如下:

@Results(id = "BaseResult", value = {@Result(column = "delete_flag", property = "deleteFlag"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")})@ResultMap(value = "BaseResult")@Select("select * from userinfo where id = #{id}")UserInfo queryUserInfoById(Integer id);

在这里插入图片描述


🥦3. mybatis的其他配置

3.1 mybatis的日志打印

大家可以发现,在上面程序的运行结果中,打印了我们此次执行的 sql 语句的具体内容,传入的参数,sql的执行结果,影响行数等日志。
在这里插入图片描述

通过这些内容我们可以更加清晰地了解 sql 的执行情况,以及在程序执行出错时分析是否是 sql的书写出现了错误。

因此当我们需要这些信息时,可以在 application.yml 或 application.properties 文件中进行以下配置:

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

3.2 配置驼峰自动转换

若因为命名规范不同导致 数据库字段和Java实体类属性的命名不一致,且需要对这些属性进行正确映射时,可以在 application.yml 或 application.properties 文件中进行以下配置:

mybatis:configuration: map-underscore-to-camel-case: true 

🍉4. 使用XML的方式编写 SQL

4.1 在mapper包下创建一个对应的 Mapper接口,并创建对应的实体类

在这里插入图片描述

4.2 声明接口方法(参数,返回值)

package com.xuan.mybatis.mapper;
import com.xuan.mybatis.model.Student;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface StudentInfoXmlMapper {// 查询操作List<Student> queryAllStudentInfo();// 新增操作Integer insert(String name, Integer age, String phone);// 删除操作Integer deleteUser (String name, String phone);// 修改操作Integer update(Student studentInfo);}

4.3 创建 xml 文件进行映射配置并编写 sql

首先我们需要在resource目录下创建一个 mapper文件夹,将创建的 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="com.xuan.mybatis.mapper.StudentInfoXmlMapper"></mapper>

在这里插入图片描述

以上配置为固定的格式,其中在不同的XML文件中 namespace 的值不同,其值为:接口所在路径 + 接口名称

============这是分隔线
注意:

  • 使用标签的编写 sql 语句与注解的方式类似,对于增删改查的 sql操作分别对应使用 insert、delete、update、select标签。
  • 由于XML文件的映射配置只指定了接口所在的位置,因此我们在写每个方法对应的 sql 语句时需要使用 id 指定接口的方法名称。
  • 因为修改操作(增删改)可以不用接收返回结果,而查询操作有返回结果集,因此使用 select 标签还需指定数据库返回的每条记录 对应的Java实体类的类型。

代码示例如下:

<?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="com.xuan.mybatis.mapper.StudentInfoXmlMapper"><insert id="insert">insert into student (name, age, phone) values (#{name}, #{age}, #{phone})</insert><update id="update">update student set phone = #{phone} where name = #{name}</update><delete id="deleteUser">delete from student where name = #{name} or phone = #{phone}</delete><select id="queryAllStudentInfo" resultType="com.xuan.mybatis.model.Student">select * from student</select></mapper>

在这里插入图片描述

4.4 使用 Alt + insert 生成测试类并执行测试方法

注意:

  1. 需在测试类加上 @SpringBootTest注解,并使用@Autowired 注入 StudentInfoXmlMapper属性)
  2. 在IDEA对 sql 语句进行测试,还需在 application.yml 文件下配置mybatis中 xml 文件的文件路径,其中 classpath代表在 resource 目录下,**Mapper.xml表示以 Mapper.xml 为结尾的所有文件。

在这里插入图片描述

mybatis:mapper-locations: classpath:mapper/**Mapper.xml
package com.xuan.mybatis.mapper;import com.xuan.mybatis.model.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class StudentInfoXmlMapperTest {@Autowiredprivate StudentInfoXmlMapper studentInfoXmlMapper;@Testvoid queryAllStudentInfo() {System.out.println(studentInfoXmlMapper.queryAllStudentInfo());;}@Testvoid insert() {studentInfoXmlMapper.insert("zhaoliu", 16, "12345678900");System.out.println();}@Testvoid deleteUser() {studentInfoXmlMapper.deleteUser("zhangsan", "18612340002");}@Testvoid update() {Student student = new Student();student.setName("admin");student.setPhone("00987654321");studentInfoXmlMapper.update(student);}}

程序的执行结果如下:
在这里插入图片描述

获取主键

使用 XML的方式获取主键与使用注解的方式类似,只需在 insert 标签中将 useGenerateKeys设置为 ture,并使用keyProperty将返回的主键值赋值给指定属性。

具体使用示例如下:

// 接口方法
Integer insert2(Student student);
// 测试类代码
void insert2() {Student student = new Student();student.setName("xiaoming");student.setAge(15);student.setPhone("123456");studentInfoXmlMapper.insert2(student);System.out.println("id: " + student.getId());
}
<insert id="insert2" useGeneratedKeys="true" keyProperty="id">insert into student (name, age, phone) values (#{name}, #{age}, #{phone})
</insert>

程序运行结果如下:
在这里插入图片描述

解决结果映射问题

在 XML 文件中解决结果映射的方式是使用 < resultMap> 标签,使用示例如下:

<resultMap id="baseMap" type="com.xuan.mybatis.model.UserInfo"><result column="delete_flag" property="deleteFlag"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result>
</resultMap>

其中 id 为该映射结果集的名称,以便其他的查询操作进行复用; type的值 为返回结果映射的类型。在< resultMap> 标签下的 < result> 标签为每个属性的一一映射关系,column 为数据库字段的名称,property为 Java实体类属性的名称。


🍋5. #{} 和 ${}

在 sql语句 中传参的方式有两种:#{} 和 ${}。可以发现在之前的代码演示中都是使用 #{ }对参数进行传递,那么两种传参的方式有何区别呢?

当参数为 Integer类型时:
在这里插入图片描述

当参数为 String 类型时:

在这里插入图片描述
通过上面两个例子可以发现:

  • #{ }传参是用 ?作为占位符,并用实际传入的参数替换 ?占位符。且当参数 Integer等类型时,构造的 sql 语句的方式是直接替换;当参数是 String 类型**时,构造 sql 语句的方式是将参数 放在" "中再进行替换==
  • ==${ }传参方式是将参数进行直接拼接

由于直接拼接的方式带来的 sql 缺陷,因此我们通常会使用#{ }对参数进行传递。但是使用#{ }并不是万能的,在某些场景下只能使用 ${ }才能构造一个正确的 sql 语句。
例如:
1.当我们要通过参数实现对查询返回结果进行 升序或降序 处理时,需要对 desc或asc 这两个字符串进行直接拼接,因此使用 #{ } 会使sql构造出错,并不能达到预期的效果。
2.当我们要使用 like 关键字进行模糊查询时,使用 #{ }将参数进行替换会自动加上 " " ,因此导致程序报错。

错误代码演示如下:
在这里插入图片描述
-在这里插入图片描述

============这是分隔线

对于 #{ }和${ }的使用,其实上述这些区别 ${ }都可以通过手动加引号的方式进行改进,达到和 #{ }一样的效果,但它们之间其实还有一个最本质的区别:使用#{ }可以防止 SQL注入;而使用 ${ }因为参数是采用直接拼接的方式,因此如果没有严格的参数校验,比较容易发生 SQL注入的问题。(关于SQL注入攻击这里不展开叙述,大家可以自行去了解)

总结:

  1. #{ }传参是进行预编译处理,${ }传参是将参数进行直接拼接
  2. 需要进行模糊查询 或 对查询结果进行升降序排序 只能使用${ }完成
  3. #{ }可以防止SQL注入攻击,因此大部分情况下都使用 #{ }

三. 动态 SQL

动态 SQL 即可以根据参数具体的传递情况对 SQL语句进行动态拼接。
例如:在进行个人信息填写时,有些信息是必填项,部分信息则是选填项,可以根据实际情况决定是否填写,因此使用myabtis 提供的动态SQL 这一强大特性可以很好解决这一问题。

🍚if 标签

if 标签的使用示例如下:

<select id="queryStudentByIdOrAge" resultType="com.xuan.mybatis.model.Student">select * from student where id > #{id}<if test="age != null">or age &lt; #{age}</if>
</select>

当 if 标签 test中的内容为true时, 标签内的内容会被拼接到 SQL语句中。(注意:由于 < 在XML为非法字符,不能直接出现在SQL语句中,故用 &lt ;来代替)

🍥trim 标签

trim标签的使用示例如下:

<insert id="insert2">insert into student<trim prefix="(" suffix=")" prefixOverrides="," suffixOverrides=","><if test="name != null">name,</if><if test="age != null">age</if></trim>values<trim prefix="(" suffix=")" prefixOverrides="," suffixOverrides=","><if test="name != null">#{name},</if><if test="age != null">#{age}</if></trim></insert>

当我们进行动态 SQL拼接时,若有部分字段没有进行传参,可以会出现前导或后缀的多余标点符号,trim 标签中 prefixOverrides和suffixOverrides 可以分别删除指定的前导和后缀符号;prefix 和 suffix可以分别添加前导和后缀符号,减少( )的添加,提供更加直观的 SQL语句。

🍭where 标签

where标签的使用示例如下:

<select id="queryStudentByIdOrAge" resultType="com.xuan.mybatis.model.Student">select * from student<where><if test="id != null">id > #{id}</if><if test="age != null">or age &lt; #{age}</if></where></select>

where 标签只有在子元素有内容时才添加 where关键字,且会自动去除子句开头多余的AND 或 OR 关键字。

where 标签页可使用 trim标签来替代:< trim prefix=“where” prefixOverrides=“and”> < /trim>。但是当子元素没有内容时,where关键字会保留,可能导致 SQL语句出现错误。

🍦set 标签

set标签使用示例如下:

<update id="update">update student<set><if test="phone != null">phone = #{phone}</if><if test="gender != null">,gender = #{gender}</if></set>where name = #{name}
</update>

set 标签用于 update语句中,可以更新指定的动态内容,并且会自动删除多余的前导或后缀逗号。

🧊foreach 标签

foreach标签使用示例如下:

<select id="queryBatchStudent" resultType="com.xuan.mybatis.model.Student">select * from student where id in <foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>
</select>

foreach 标签通常搭配 in 关键字使用,foreach 传入的参数可以是任意可迭代的对象(List、Set等)、Map对象或 数组等;其中 collection为参数的名称,item 为每个元素的名称,seperator 为元素间的分隔符,open为添加前缀,close为添加后缀。
注意:当传入参数类型为List集合时 或 数组时,最好将参数名称命名为 list 或 array,因为在不同依赖下参数名若不为 list或array 可能导致报错。

🍬sql 和 include 标签

在 XML文件中,当很多的 SQL语句出现了重复的片段时,我们可以将重复的部分使用 sql 标签进行提取,再通过 include 标签对该片段进行引用。

sql 和 include 标签使用示例如下:

<sql id="primaryColumn">id, name, age, phone
</sql><select id="queryAllStudentInfo" resultType="com.xuan.mybatis.model.Student">select <include refid="primaryColumn"></include>from student
</select>

sql 标签的作用是定义重复片段。id 的值为该片段的名称,作为引用的标识。
include 标签的作用是引用重复片段。refid 的值为引用片段的名称。


以上就是本篇文章的全部内容了,如果这篇文章对你有些许帮助,你的点赞、收藏和评论就是对我最大的支持。
另外,文章的不足之处,也希望你可以给我一点小小的建议,我会努力检查并改进。

相关文章:

【MyBatis】快速入门MyBatis(保姆式教学),你值得一看

文章目录 &#x1f4c4;前言一. Mybatis简介✈️1. 什么是Mybatis&#x1f680;2. 为什么使用Mybatis 二. Mybatis快速入门&#x1f346;1. mybatis使用前准备1.1 创建springboot项目并引入相关依赖1.2 在 application.ym中进行数据源的配置1.3 创建数据表&#xff0c;准备表数…...

git pull代码时候报错:error: cannot open .git/FETCH_HEAD: Permission denied

git pull代码时候报错&#xff1a; error: cannot open .git/FETCH_HEAD: Permission denied 原因&#xff1a; 当前登录用户没有修改目录的权限。 解决办法&#xff1a; 修改当前目录权限 1. whoami 查看当前登录用户 xxx$ whoami 假设上边查询登陆账号为&#xff1a;csd…...

shell - 正则表达式和grep命令和sed命令

一.正则表达式概述 1.正则表达式定义 1.1 定义 使用字符串描述、匹配一系列符合某个规则的字符串 1.2 了解 普通字符&#xff1a; 大小写字母、数字、标点符号及一些其它符号元字符&#xff1a; 在正则表达式中具有特殊意义的专用字符 1.3 层次分类 基础正则表达式扩展正…...

datawhale 大模型学习 第十二章-大模型环境影响

环境影响概述 气候变化&#xff1a;大语言模型&#xff08;LLM&#xff09;的训练和运行需要大量计算资源&#xff0c;导致显著的能源消耗和温室气体排放&#xff0c;加剧气候变化。能源消耗&#xff1a;训练LLM的计算过程消耗大量电力&#xff0c;间接增加了化石燃料的使用&a…...

Qt WebEngine模块使用(开发环境安装和程序开发)

一、Qt WebEngine Qt WebEngine_hitzsf的博客-CSDN博客 Qt WebEngine模块提供了一个Web浏览器引擎&#xff0c;可以轻松地将万维网上的内容嵌入到没有本机Web引擎的平台上的Qt应用程序中。Qt WebEngine提供了用于渲染HTML&#xff0c;XHTML和SVG文档的C 类和QML类型&#xff…...

网络体系结构 和网络原理之UDP和TCP

目录 网络分层 一. 应用层 http协议 二. 传输层 1. 介绍 2.UDP协议 (1)组成 (2)细节 3.TCP协议 (1)特性如下链接&#xff1a; (2)组成 (3)特点 三. 网络层 四. 数据链路层 1.介绍 2.以太网协议 3.mac地址和ip地址 五. 物理层 DNS 网络分层 一. 应用层 应用程序 现成的…...

将Android APP安装到sm8550 HDK的NVMe SSD

APP存储路径 在Android中&#xff0c;App在运行过程中主要访问的数据路径通常包括以下几个方面&#xff1a; 内部存储&#xff08;Internal Storage&#xff09;&#xff1a;App会访问其私有的内部存储空间&#xff0c;这个空间通常位于&#xff1a; /data/data/<package…...

(Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息

国家青藏高原科学数据中心下载中国1千米分辨率逐日全天候地表土壤水分数据集&#xff08;2003-2022&#xff09; 问题&#xff1a;数据在arcgis打开特别大&#xff0c;无法和矢量数据重合&#xff0c;没有设置地理坐标系 数据在网站上提供了投影信息&#xff0c;提示可以进行py…...

Linux:进度条的创建

目录 使用工具的简单介绍&#xff1a; \r &#xff1a; fflush &#xff1a; 倒计时的创建&#xff1a; 倒计时的工作原理&#xff1a; 进度条的创建&#xff1a; 不同场景下、打印任意长度的进度条&#xff1a; main .c procbor.c 测试效果&#xff1a; 使用工具…...

treeview

QML自定义一个TreeView&#xff0c;使用ListView递归 在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件&#xff08;在 Qt6 中出了一个继承自 TableView 的 TreeView&#xff09;&#xff0c;而且 QtQuick.Controls 1.x 中的也需要配合 C model 来自定义&#xff0c…...

Android开发中自定义View实现RecyclerView下划线

本篇文章主要讲解的是有关RecyclerView下划线的使用&#xff0c;主要有几个方法&#xff0c;具体如下&#xff1a; 第一种方式&#xff1a;网格分割线 public class GridDivider extends RecyclerView.ItemDecoration { private Drawable mDividerDarwable; private i…...

MySQL前百分之N问题--percent_rank()函数

PERCENT_RANK()函数 PERCENT_RANK()函数用于将每行按照(rank - 1) / (rows - 1)进行计算,用以求MySQL中前百分之N问题。其中&#xff0c;rank为RANK()函数产生的序号&#xff0c;rows为当前窗口的记录总行数 PERCENT_RANK()函数返回介于 0 和 1 之间的小数值 selectstudent_…...

【高效开发工具系列】Wolfram Alpha

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

分享7种SQL的进阶用法

推荐一款ChatGPT4.0国内站点,每日有免费使用额度,支持PC、APP、VScode插件同步使用 SQL(Structured Query Language)是一种强大的数据库查询和操作语言,它用于与关系数据库进行交互。随着数据的不断增长和应用需求的日益复杂,掌握SQL的进阶用法对于数据库管理员、数据分析…...

protobuf-go pragma.go 文件介绍

pragma.go 文件 文件位于&#xff1a; https://github.com/protocolbuffers/protobuf-go/blob/master/internal/pragma/pragma.go 该文件核心思想&#xff1a; 利用 Golang 语法机制&#xff0c;扩展 Golang 语言特性 目前&#xff0c;该文件提供以下 4 个功能&#xff1a; …...

C#设置程序开机启动

1&#xff1a;获取当前用户&#xff1a; System.Security.Principal.WindowsIdentity identity System.Security.Principal.WindowsIdentity.GetCurrent();System.Security.Principal.WindowsPrincipal principal new System.Security.Principal.WindowsPrincipal(identity);…...

爱可声助听器参与南湖区价值百万公益助残捐赠活动成功举行

“声音大小合适吗&#xff1f;能听清楚吗&#xff1f;”今天下午&#xff0c;一场助残捐赠活动在南湖区凤桥镇悄然举行&#xff0c;杭州爱听科技有限公司带着验配团队和听力检测设备来到活动现场&#xff0c;为南湖区听障残疾人和老人适配助听器。 家住余新镇的75岁的周奶奶身体…...

SpringBoot 实现定时任务

在项目我们会有很多需要在某一特定时刻自动触发某一时间的需求&#xff0c;例如我们提交订单但未支付的超过一定时间后需要自动取消订单。 定时任务实现的几种方式&#xff1a; Timer&#xff1a;java自带的java.util.Timer类&#xff0c;使用这种方式允许你调度一个java.util…...

将Vue2中的console.log调试信息移除

前端项目构建生产环境下的package时&#xff0c;咱们肯定要去掉development环境下的console.log&#xff0c;如果挨个注释可就太费劲了&#xff0c;本文介绍怎么使用 babel-plugin-transform-remove-console 移除前端项目中所有的console.log. 1. 安装依赖 npm install babel-…...

EMC设计检查建议,让PCB layout达到最佳性能

EMC&#xff1a;Electro Magnetic Compatibility的简称&#xff0c;也称电磁兼容&#xff0c;各种电气或电子设备在电磁环境复杂的共同空间中&#xff0c;以规定的安全系数满足设计要求的正常工作能力。 本章对于 RK3588产品设计中的 ESD/EMI防护设计及EMC的设计检查给出了建议…...

常用抓包软件集合(Fiddler、Charles)

1. Fiddler 介绍&#xff1a;Fiddler是一个免费的HTTP和HTTPS调试工具&#xff0c;支持Windows平台。它可以捕获HTTP和HTTPS流量&#xff0c;并提供了丰富的调试和分析功能。优点&#xff1a;易于安装、易于使用、支持多种扩展、可以提高开发效率。缺点&#xff1a;只支持Wind…...

C++入门(一)— 使用VScode开发简介

文章目录 C 介绍C 擅长领域C 程序是如何开发编译器、链接器和库编译预处理编译阶段汇编阶段链接阶段 安装集成开发环境 &#xff08;IDE&#xff09;配置编译器&#xff1a;构建配置配置编译器&#xff1a;编译器扩展配置编译器&#xff1a;警告和错误级别配置编译器&#xff1…...

PeakCAN连接到WSL2 Debian

操作步骤 按照以下步骤进行操作&#xff1a; 在Windows下安装PeakCAN驱动并安装&#xff0c;地址是https://www.peak-system.com/PCAN-USB.199.0.html?&L1 在Windows下安装usbipd&#xff0c;地址是https://github.com/dorssel/usbipd-win/releases&#xff0c;最新版是…...

Spring Boot导出EXCEL 文件

主要功能:实现java导出excel到本地 JDK版本&#xff1a;openJDK 20.0.1 依赖pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchem…...

编程笔记 html5cssjs 060 css响应式布局

编程笔记 html5&css&js 060 css响应式布局 一、响应式布局二、Bootstrap简介总结 CSS响应式布局是一种可以在不同设备&#xff08;例如桌面电脑、平板电脑、手机等&#xff09;上自动调整页面布局和样式的技术。 一、响应式布局 使用CSS响应式布局的关键是媒体查询&am…...

建筑行业如何应用3D开发工具HOOPS提升实时设计体验?

建筑行业一直在迅速发展&#xff0c;技术的不断创新也为其带来了新的机遇与挑战。在这一领域&#xff0c;三维图形技术的应用变得尤为重要。HOOPS技术&#xff0c;作为一套用于开发三维图形应用程序的工具和库&#xff0c;为建筑行业带来了深刻的变革。本文将探讨HOOPS技术在建…...

【grafana】使用教程

【grafana】使用教程 一、简介二、下载及安装及配置三、基本概念3.1 数据源&#xff08;Data Source&#xff09;3.2 仪表盘&#xff08;Dashboard&#xff09;3.3 Panel&#xff08;面板&#xff09;3.4 ROW&#xff08;行&#xff09;3.5 共享及自定义 四、常用可视化示例4.1…...

seata 分布式

一、下载安装seata 已经下载好的朋友可以跳过这个步骤。这里下载的是seata1.6.1这个版本。 1、进入seata官网 地址&#xff1a; https://seata.io/zh-cn/index.html 2、进入下载 3、点击下载地址 下载地址&#xff1a; https://github.com/seata/seata 二、配置seata 进入c…...

前端面试题-说说你了解的js数据结构?(2024.1.29)

1、数组 (Array) 数组是一组有序的值的集合&#xff0c;可以通过索引访问。JavaScript 数组可以包含不同的数据类型&#xff0c;并且长度是动态的。 let myArray [1, hello, true, [2, 3]];2、对象 (Object) 对象是无序的键值对的集合。每个键都是字符串或符号&#xff0c;…...

音视频数字化(数字与模拟-录音机)

之前我们说了【数字与模拟-照相机】照相机的数字化,今天聊聊录音机。 说录音机之前,必须说说留声机。留声机是爱迪生1877年宣布发明成功的,研发过程相当复杂,但原理是简单的。 声音的本质是“波”,是物体振动产生的。以乐器为例,打击乐就是敲击(鼓、钹、木鱼、木琴、三…...