【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的使用步骤:
- 创建数据库连接池 DataSource
- 通过连接池 DataSource 获取数据库连接 Connection
- 编写带 ?占位符的SQL语句
- 通过Connection 和 SQL语句 创建PreparedStatement对象
- 通过PreparedStatement对象对 ?占位符逐一替换
- 执行SQL语句(查询操作或修改操作)
- 若执行查询操作,需要对返回的结果集对象(ResultSet)进行处理
- 释放资源(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操作数据库步骤如下:
- 在application.yml 或 application.properties 配置文件中进行数据库的参数配置(整个程序只需配置一次,等同于创建数据库连接池DataSource)
- 进行访问数据库方法的定义
- 使用 注解或XML 的方式编写SQL语句
- 使用定义的方法执行SQL语句(查询操作或修改操作)
- 若为查询操作,只需使用集合接收查询结果,无需对结果集进行处理
使用代码示例如下:

@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中字段的命名规范(用 _ 作为分隔符)不同。
如何解决结果映射问题呢?
- 最直接的方法是在构造 SQL语句时 使用 as 给返回结果的列起别名。(不推荐,因为每个 sql 语句都需要进行同样的操作)
- 使用注解的方式给所有需要映射字段作说明(可行,但不是最佳的方式)
- 在 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 生成测试类并执行测试方法
注意:
- 需在测试类加上 @SpringBootTest注解,并使用@Autowired 注入 StudentInfoXmlMapper属性)
- 在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注入攻击这里不展开叙述,大家可以自行去了解)
总结:
- #{ }传参是进行预编译处理,${ }传参是将参数进行直接拼接
- 需要进行模糊查询 或 对查询结果进行升降序排序 只能使用${ }完成
- #{ }可以防止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 < #{age}</if>
</select>
当 if 标签 test中的内容为true时, 标签内的内容会被拼接到 SQL语句中。(注意:由于 < 在XML为非法字符,不能直接出现在SQL语句中,故用 < ;来代替)
🍥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 < #{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(保姆式教学),你值得一看
文章目录 📄前言一. Mybatis简介✈️1. 什么是Mybatis🚀2. 为什么使用Mybatis 二. Mybatis快速入门🍆1. mybatis使用前准备1.1 创建springboot项目并引入相关依赖1.2 在 application.ym中进行数据源的配置1.3 创建数据表,准备表数…...
git pull代码时候报错:error: cannot open .git/FETCH_HEAD: Permission denied
git pull代码时候报错: error: cannot open .git/FETCH_HEAD: Permission denied 原因: 当前登录用户没有修改目录的权限。 解决办法: 修改当前目录权限 1. whoami 查看当前登录用户 xxx$ whoami 假设上边查询登陆账号为:csd…...
shell - 正则表达式和grep命令和sed命令
一.正则表达式概述 1.正则表达式定义 1.1 定义 使用字符串描述、匹配一系列符合某个规则的字符串 1.2 了解 普通字符: 大小写字母、数字、标点符号及一些其它符号元字符: 在正则表达式中具有特殊意义的专用字符 1.3 层次分类 基础正则表达式扩展正…...
datawhale 大模型学习 第十二章-大模型环境影响
环境影响概述 气候变化:大语言模型(LLM)的训练和运行需要大量计算资源,导致显著的能源消耗和温室气体排放,加剧气候变化。能源消耗:训练LLM的计算过程消耗大量电力,间接增加了化石燃料的使用&a…...
Qt WebEngine模块使用(开发环境安装和程序开发)
一、Qt WebEngine Qt WebEngine_hitzsf的博客-CSDN博客 Qt WebEngine模块提供了一个Web浏览器引擎,可以轻松地将万维网上的内容嵌入到没有本机Web引擎的平台上的Qt应用程序中。Qt WebEngine提供了用于渲染HTML,XHTML和SVG文档的C 类和QML类型ÿ…...
网络体系结构 和网络原理之UDP和TCP
目录 网络分层 一. 应用层 http协议 二. 传输层 1. 介绍 2.UDP协议 (1)组成 (2)细节 3.TCP协议 (1)特性如下链接: (2)组成 (3)特点 三. 网络层 四. 数据链路层 1.介绍 2.以太网协议 3.mac地址和ip地址 五. 物理层 DNS 网络分层 一. 应用层 应用程序 现成的…...
将Android APP安装到sm8550 HDK的NVMe SSD
APP存储路径 在Android中,App在运行过程中主要访问的数据路径通常包括以下几个方面: 内部存储(Internal Storage):App会访问其私有的内部存储空间,这个空间通常位于: /data/data/<package…...
(Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
国家青藏高原科学数据中心下载中国1千米分辨率逐日全天候地表土壤水分数据集(2003-2022) 问题:数据在arcgis打开特别大,无法和矢量数据重合,没有设置地理坐标系 数据在网站上提供了投影信息,提示可以进行py…...
Linux:进度条的创建
目录 使用工具的简单介绍: \r : fflush : 倒计时的创建: 倒计时的工作原理: 进度条的创建: 不同场景下、打印任意长度的进度条: main .c procbor.c 测试效果: 使用工具…...
treeview
QML自定义一个TreeView,使用ListView递归 在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件(在 Qt6 中出了一个继承自 TableView 的 TreeView),而且 QtQuick.Controls 1.x 中的也需要配合 C model 来自定义,…...
Android开发中自定义View实现RecyclerView下划线
本篇文章主要讲解的是有关RecyclerView下划线的使用,主要有几个方法,具体如下: 第一种方式:网格分割线 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问题。其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数 PERCENT_RANK()函数返回介于 0 和 1 之间的小数值 selectstudent_…...
【高效开发工具系列】Wolfram Alpha
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
分享7种SQL的进阶用法
推荐一款ChatGPT4.0国内站点,每日有免费使用额度,支持PC、APP、VScode插件同步使用 SQL(Structured Query Language)是一种强大的数据库查询和操作语言,它用于与关系数据库进行交互。随着数据的不断增长和应用需求的日益复杂,掌握SQL的进阶用法对于数据库管理员、数据分析…...
protobuf-go pragma.go 文件介绍
pragma.go 文件 文件位于: https://github.com/protocolbuffers/protobuf-go/blob/master/internal/pragma/pragma.go 该文件核心思想: 利用 Golang 语法机制,扩展 Golang 语言特性 目前,该文件提供以下 4 个功能: …...
C#设置程序开机启动
1:获取当前用户: System.Security.Principal.WindowsIdentity identity System.Security.Principal.WindowsIdentity.GetCurrent();System.Security.Principal.WindowsPrincipal principal new System.Security.Principal.WindowsPrincipal(identity);…...
爱可声助听器参与南湖区价值百万公益助残捐赠活动成功举行
“声音大小合适吗?能听清楚吗?”今天下午,一场助残捐赠活动在南湖区凤桥镇悄然举行,杭州爱听科技有限公司带着验配团队和听力检测设备来到活动现场,为南湖区听障残疾人和老人适配助听器。 家住余新镇的75岁的周奶奶身体…...
SpringBoot 实现定时任务
在项目我们会有很多需要在某一特定时刻自动触发某一时间的需求,例如我们提交订单但未支付的超过一定时间后需要自动取消订单。 定时任务实现的几种方式: Timer:java自带的java.util.Timer类,使用这种方式允许你调度一个java.util…...
将Vue2中的console.log调试信息移除
前端项目构建生产环境下的package时,咱们肯定要去掉development环境下的console.log,如果挨个注释可就太费劲了,本文介绍怎么使用 babel-plugin-transform-remove-console 移除前端项目中所有的console.log. 1. 安装依赖 npm install babel-…...
EMC设计检查建议,让PCB layout达到最佳性能
EMC:Electro Magnetic Compatibility的简称,也称电磁兼容,各种电气或电子设备在电磁环境复杂的共同空间中,以规定的安全系数满足设计要求的正常工作能力。 本章对于 RK3588产品设计中的 ESD/EMI防护设计及EMC的设计检查给出了建议…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...
