【JavaWeb后端开发04】java操作数据库(JDBC + Mybatis+ yml格式)详解

文章目录

    • 1. 前言
    • 2. JDBC
      • 2.1 介绍
      • 2.2 入门程序
        • 2.2.1 DataGrip
        • 2.2.2 在IDEA执行sql语句
      • 2.3 查询数据案例
        • 2.3.1 需求
        • 2.3.2 准备工作
        • 2.3.3 AI代码实现
        • 2.3.4 代码剖析
          • 2.3.4.1 ResultSet
          • 2.3.4.2 预编译SQL
            • 2.3.4.2.1 SQL注入
            • 2.3.4.2.2 SQL注入解决
            • 2.3.4.2.3 性能更高
      • 2.4 增删改数据
        • 2.4.1 需求
        • 2.4.2 代码实现
    • 3. Mybatis
      • 3.1 介绍
        • 3.1.1 快速入门
        • 3.1.2 辅助配置
          • 3.1.2.1 配置SQL提示
          • 3.1.2.2 配置Mybatis日志输出
        • 3.1.3 JDBC VS Mybatis
        • 3.1.4 数据库连接池
          • 3.1.4.1 介绍
          • 3.1.4.2 产品
        • 3.1.5 增删改查操作
          • 3.1.5.1 删除
          • 3.1.5.2 新增
          • 3.1.5.3 修改
          • 3.1.5.4 查询(带条件)
        • 3.1.6 XML映射配置
          • 3.1.6.1 XML配置文件规范
          • 3.1.6.2 XML配置文件实现
          • 3.1.6.3 MybatisX的使用
    • 4. SpringBoot配置文件
      • 4.1 介绍
      • 4.2 语法
      • 4.3 案例


1. 前言

在前面我们学习MySQL数据库时,都是利用图形化客户端工具(如:idea、datagrip),来操作数据库的。

我们做为后端程序开发人员,通常会使用Java程序来完成对数据库的操作。Java程序操作数据库的技术呢,有很多啊,而最为底层、最为基础的就是JDBC。

JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。 【是操作数据库最为基础、底层的技术】

但是使用JDBC来操作数据库,会比较繁琐,所以现在在企业项目开发中呢,一般都会使用基于JDBC的封装的高级框架,比如:Mybatis、MybatisPlus、Hibernate、SpringDataJPA。

而这些技术,目前的市场占有份额如下图所示:

从上图中,我们也可以看到,目前最为主流的就是Mybatis,其次是MybatisPlus。

内容:

  1. JDBC

  2. Mybatis

  3. SpringBoot配置文件

2. JDBC

2.1 介绍

JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。

本质:

  • sun公司官方定义的一套操作所有关系型数据库的规范,即接口

  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包。

  • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

那有了JDBC之后,我们就可以直接在java代码中来操作数据库了,只需要编写这样一段java代码,就可以来操作数据库中的数据。 示例代码如下:

2.2 入门程序

需求:基于JDBC,执行更新数据库数据语句

image-20250421164903758

2.2.1 DataGrip

创建数据表

create table user(id int unsigned primary key auto_increment comment 'ID,主键',username varchar(20) comment '用户名',password varchar(32) comment '密码',name varchar(10) comment '姓名',age tinyint unsigned comment '年龄'
) comment '用户表';insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大乔', 22),(2, 'xiaoqiao', '123456', '小乔', 18),(3, 'diaochan', '123456', '貂蝉', 24),(4, 'lvbu', '123456', '吕布', 28),(5, 'zhaoyun', '12345678', '赵云', 27);

image-20250421171247331


2.2.2 在IDEA执行sql语句

导入依赖

    <dependencies><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.9.3</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies>
  1. mysql-connector-j (MySQL 连接器)

    用途:这是 MySQL 数据库的 JDBC 驱动程序,它允许 Java 程序与 MySQL 数据库进行连接和交互。

    功能:通过这个依赖,Java 程序可以使用 JDBC(Java Database Connectivity)接口与 MySQL 数据库进行数据操作(如查询、更新、删除等)。

  2. junit-jupiter (JUnit 测试框架)

    用途:这是 JUnit 5 的核心库,提供了用于编写和执行单元测试的功能。junit-jupiter 是 JUnit 5 框架的一部分,包含了新的测试注解和断言方法。

    功能:它允许开发人员编写单元测试,以确保代码的正确性。JUnit 5 允许使用如 @Test 注解标记测试方法,支持断言(如 assertEquals()assertTrue())来验证预期结果。

  3. lombok (Lombok 库)

用途:Lombok 是一个 Java 库,通过注解自动生成常见的 Java 代码(如 getter、setter、toString 方法等),减少了代码冗余。

功能:它通过注解(如 @Getter@Setter@ToString@EqualsAndHashCode)自动为类生成常见的方法,简化了 Java 类的编写。使用 Lombok,开发者不需要手动编写大量样板代码,可以让代码更加简洁、清晰。

更新代码

import com.mysql.cj.jdbc.Driver;
import org.junit.jupiter.api.Test;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;public class JdbcTest {/*** Jdbc入门程序*/@Testpublic void testUpdate() throws Exception {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取数据库连接String url = "jdbc:mysql://localhost:3306/web01";String username = "root";String password = "0524";Connection connection = DriverManager.getConnection(url, username, password);//3.获取sql语句的执行对象Statement statement = connection.createStatement();//4.执行SQLint i = statement.executeUpdate("update user set age = 25 where id = 1");System.out.println("SQL执行完毕影响记录数为:" + i);//5.释放资源statement.close();connection.close();}
}
  1. 注册驱动

    Class.forName():是 Java 反射机制中的一个方法,作用是加载并初始化指定类。Class.forName() 会通过类的全限定名(包括包名)加载指定的类,并且会执行该类的静态初始化块。

    "com.mysql.cj.jdbc.Driver":是 MySQL JDBC 驱动类的全限定类名(包括包名)。它是 MySQL 的驱动程序类,负责将 Java 程序与 MySQL 数据库之间的通信进行处理。获取数据库连接

    connection = DriverManager.getConnection使用connection进行数据库连接,需要url地址、用户、密码

    "jdbc:mysql://localhost:3306/web01";:

    • jdbc:mysql://:这是 JDBC (Java Database Connectivity) 的协议部分,表示这是一个 MySQL 数据库连接。
    • localhost:这是数据库的主机名,表示数据库在本地计算机上运行。
    • 3306:这是 MySQL 数据库的默认端口号,表示数据库服务监听的端口。
    • web01:这是数据库的名称,表示要连接的数据库是名为 web01 的数据库。
  2. 获取sql语句执行对象

    statement执行更新sql语句,并返回影响几条记录(int)

  3. 执行SQL语句

    • executeUpdate用于执行修改数据库内容的 SQL 语句(如 INSERTUPDATEDELETE)。

    • executeQuery用于执行选择SELECT语句,查询数据库并返回结果集ResultSet,下一节会用到

      ResultSet rs = statement.executeQuery("SELECT * FROM users");
    • execute():执行任何 SQL 语句,无论是否返回结果集。该方法适用于 SELECTINSERTUPDATEDELETE 等多种语句。

      返回值:返回一个布尔值,指示执行的 SQL 是否返回一个结果集。

  4. 执行完毕释放资源

    statement.close();connection.close(); 用于关闭数据库连接和声明,以确保资源得到妥善释放。

    • 如果不关闭 statement,可能会导致资源泄漏,特别是对于数据库连接的声明,可能会影响性能和稳定性。
    • 数据库连接是宝贵的资源,如果不及时关闭connection,可能会耗尽数据库连接池的可用连接,导致系统性能下降或连接异常。

最终结果

image-20250421171441217


2.3 查询数据案例

2.3.1 需求

image-20250421174100658

需求:基于JDBC实现用户登录功能。用户登录就是你输入的账号名和密码可以在数据库中使用SELECT语句查询到,能查到就放你登录

本质:其本质呢,其实就是基于JDBC程序,执行如下select语句,并将查询的结果输出到控制台。SQL语句:

select * from user where username = 'linchong' and password = '123456';
2.3.2 准备工作

1). 创建一个maven项目

2). 创建一个数据库 web,并在该数据库中创建user表

create table user(id int unsigned primary key auto_increment comment 'ID,主键',username varchar(20) comment '用户名',password varchar(32) comment '密码',name varchar(10) comment '姓名',age tinyint unsigned comment '年龄'
) comment '用户表';insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大乔', 22),(2, 'xiaoqiao', '123456', '小乔', 18),(3, 'diaochan', '123456', '貂蝉', 24),(4, 'lvbu', '123456', '吕布', 28),(5, 'zhaoyun', '12345678', '赵云', 27);
2.3.3 AI代码实现

AI提示语句

你是一名java开发工程师,帮我基于JDBC程序来操作数据库,执行如下SQL语句:select id,username,password,name,age from user where username = ‘daqiao’ and password = ‘123456’;
并将查询的每一行记录,都封装到实体类User中,然后将User对象的数据输出到控制台中。
User 实体类属性如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Integer age; //年龄
}

具体的代码为:

1). 在 pom.xml 文件中引入依赖

<dependencies><!-- MySQL JDBC driver --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.9.3</version><scope>test</scope></dependency>
</dependencies>

2). 在 src/main/test/java 目录下编写测试类,定义测试方法

从 JDBC 4.0 开始,Java 对 JDBC 驱动程序进行了改进,允许驱动程序自动注册。也就是说,只要你把适当的 JDBC 驱动 JAR 包(例如 mysql-connector-java)添加到项目的 classpath 中,JDBC 驱动会自动加载,无需显式地调用 Class.forName() 来加载驱动。

    @Testpublic void testSelect() throws Exception {//获取连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/web01","root","0524");//创建预编译的PreparedStatement对象PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM user WHERE username = ? and password = ?");//设置参数pstmt.setString(1,"daqiao");pstmt.setString(2,"123456");//执行查询ResultSet rs = pstmt.executeQuery();//处理解析返回的数据while(rs.next()){int id = rs.getInt("id");String username = rs.getString("username");String password = rs.getString("password");String name = rs.getString("name");int age = rs.getInt("age");System.out.println(id + " " + username + " " + password + " " + name + " " + age);}//释放资源rs.close();pstmt.close();connection.close();}}

下一节会讲解返回值rs处理部分

输出结果

image-20250421182848463

而上述的单元测试中,我们在SQL语句中,将将 用户名 和密码的值都写死了,而这两个值应该是动态的,是将来页面传递到服务端的。 那么,我们可以基于前面所讲解的JUnit中的参数化测试进行单元测试,代码改造如下:

public class JDBCTest {/*** 编写JDBC程序, 查询数据*/@ParameterizedTest@CsvSource({"daqiao,123456"})public void testJdbc(String _username, String _password) throws Exception {// 获取连接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");// 创建预编译的PreparedStatement对象PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM user WHERE username = ? AND password = ?");// 设置参数pstmt.setString(1, _username); // 第一个问号对应的参数pstmt.setString(2, _password); // 第二个问号对应的参数// 执行查询ResultSet rs = pstmt.executeQuery();// 处理结果集while (rs.next()) {int id = rs.getInt("id");String uName = rs.getString("username");String pwd = rs.getString("password");String name = rs.getString("name");int age = rs.getInt("age");System.out.println("ID: " + id + ", Username: " + uName + ", Password: " + pwd + ", Name: " + name + ", Age: " + age);}// 关闭资源rs.close();pstmt.close();conn.close();}}

如果在测试时,需要传递一组参数,可以使用 @CsvSource 注解。

image-20250421174319825

2.3.4 代码剖析
2.3.4.1 ResultSet

ResultSet(结果集对象):封装了DQL查询语句查询的结果

  • next():将光标从当前位置向前移动一行,并判断当前行是否为有效行,返回值为boolean。

    • true:有效行,当前行有数据

    • false:无效行,当前行没有数据

    • 所以可以while循环逐行读取数据,直到为空结束

  • getXxx(…):获取数据,可以根据列的编号获取,也可以根据列名获取(推荐)。

结果解析步骤:

2.3.4.2 预编译SQL

其实我们在编写SQL语句的时候,有两种风格:

  • 静态SQL(参数硬编码)
conn.prepareStatement("SELECT * FROM user WHERE username = 'daqiao' AND password = '123456'");
ResultSet resultSet = pstmt.executeQuery();

这种呢,就是参数值,直接拼接在SQL语句中,参数值是写死的。

  • 预编译SQL(参数动态传递)
conn.prepareStatement("SELECT * FROM user WHERE username = ? AND password = ?");
pstmt.setString(1, "daqiao");
pstmt.setString(2, "123456");
ResultSet resultSet = pstmt.executeQuery();

这种呢,并未将参数值在SQL语句中写死,而是使用 ? 进行占位,然后再指定每一个占位符对应的值是多少,而最终在执行SQL语句的时候,程序会将SQL语句(SELECT * FROM user WHERE username = ? AND password = ?),以及参数值(“daqiao”, “123456”)都发送给数据库,然后在执行的时候,会使用参数值,将?占位符替换掉。

那这种预编译的SQL,也是在项目开发中推荐使用的SQL语句。主要的作用有两个:

  • 防止SQL注入,更加安全

  • 性能更高

那接下来,我们就来介绍一下这两点。

2.3.4.2.1 SQL注入
  • SQL注入:通过控制输入来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

SQL注入最典型的场景,就是用户登录功能。

注入演示:

1). 打开资料中的文件夹 资料/02. SQL注入演示,运行其中的jar包 sql_Injection_demo-0.0.1-SNAPSHOT.jar,进入该目录后,执行命令:

java -jar sql_Injection_demo-0.0.1-SNAPSHOT.jar

2). 打开浏览器访问 http://localhost:9090/ ,必须登录后才能访问到系统。我们先测试正常的用户名和密码

3). 接下来,我们再来测试一下错误的用户名和密码 。

我们看到,如果用户名密码错误,是不能进入到系统中进行访问的,会提示 用户名和密码错误

4). 那接下来,我们就要演示一下SQL注入现象,我们可以通过控制表单输入,来修改事先定义好的SQL语句的含义。 从而来攻击服务器。

点击登录后,我们看到居然可以成功进入到系统中。

为什么会出现这种现象呢?

在进行登录操作时,怎么样才算登录成功呢? 如果我们查询到了数据,就说明用户名密码是对的。 如果没有查询到数据,就说明用户名或密码错误。

而出现上述现象,原因就是因为,我们我们编写的SQL语句是基于字符串进行拼接的 。 我们输入的用户名无所谓,比如:shfhsjfhja ,而密码呢,就是我们精心设计的,如:' or '1' = '1

那最终拼接的SQL语句,如下所示:

我们知道,or 连接的条件,是或的关系,两者满足其一就可以。 所以,虽然用户名密码输入错误,也是可以查询返回结果的,而只要查询到了数据,就说明用户名和密码是正确的。

2.3.4.2.2 SQL注入解决

而通过预编译SQL(select * from user where username = ? and password = ?),就可以直接解决上述SQL注入的问题。 接下来,我们再来演示一下,通过预编译SQL是否能够解决SQL注入问题。

1). 打开资料中的文件夹 资料/02. SQL注入演示,运行其中的jar包 sql_prepared_demo-0.0.1-SNAPSHOT.jar,进入该目录后,执行命令:

java -jar sql_prepared_demo-0.0.1-SNAPSHOT.jar

2). 打开浏览器访问 http://localhost:9090/ ,必须登录后才能访问到系统 。我们先测试正常的用户名和密码

3). 那接下来,我们就要演示一下是否可以基于上述的密码 ' or '1' = '1,来完成SQL注入 。

通过控制台,可以看到输入的SQL语句,是预编译SQL语句。

而在预编译SQL语句中,当我们执行的时候,会把整个' or '1'='1作为一个完整的参数,赋值给第2个问号(' or '1'='1进行了转义,只当做字符串使用)

那么此时再查询时,就查询不到对应的数据了,登录失败。

注意:在以后的项目开发中,我们使用的基本全部都是预编译SQL语句。

2.3.4.2.3 性能更高

数据库会把以前用过的sql语句直接到缓存里面拿(数据库内存),不需要在重新进行语法检查 — 编译。

2.4 增删改数据

2.4.1 需求
  • 需求:基于JDBC程序,执行如下update语句。

  • SQL:

update user set password = '123456', gender = 2 where id = 1;
2.4.2 代码实现

AI提示词(prompt):

你是一名java开发工程师,帮我基于JDBC程序来操作数据库,执行如下SQL语句:

update user set password = ‘123456’, gender = 2 where id = 1;

代码实现如下:

@ParameterizedTest
@CsvSource({"1,123456,25"})
public void testUpdate(int userId, String newPassword, int newAge) throws Exception {// 建立数据库连接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");// SQL 更新语句String sql = "UPDATE user SET password = ?, age = ? WHERE id = ?";// 创建预编译的PreparedStatement对象PreparedStatement pstmt = conn.prepareStatement(sql);// 设置参数pstmt.setString(1, newPassword); // 第一个问号对应的参数pstmt.setInt(2, newAge);      // 第二个问号对应的参数pstmt.setInt(3, userId);         // 第三个问号对应的参数// 执行更新int rowsUpdated = pstmt.executeUpdate();// 输出结果System.out.println(rowsUpdated + " row(s) updated.");// 关闭资源pstmt.close();conn.close();
}
  • JDBC程序执行DML语句:int rowsUpdated = pstmt.executeUpdate(); //返回值是影响的记录数

  • JDBC程序执行DQL语句:ResultSet resultSet = pstmt.executeQuery(); //返回值是查询结果集

image-20250421175619256

3. Mybatis

3.1 介绍

什么是MyBatis?

  • MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。

  • MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

  • 官网:https://mybatis.org/mybatis-3/zh/index.html

在上面我们提到了两个词:一个是持久层,另一个是框架。

  • 持久层:指的是就是数据访问层(dao),是用来操作数据库的。

  • 框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。

通过Mybatis就可以大大简化原生的JDBC程序的代码编写,比如 通过 select * from user 查询所有的用户数据,通过JDBC程序操作呢,需要大量的代码实现,而如果通过Mybatis实现相同的功能,只需要简单的三四行就可以搞定。

3.1.1 快速入门

需求:使用Mybatis查询所有用户数据 。

image-20250421213027553

1). 创建springboot工程,并导入 mybatis的起步依赖、mysql的驱动包、lombok。

项目工程创建完成后,自动在pom.xml文件中,导入Mybatis依赖和MySQL驱动依赖。如下所示:

2). 数据准备:创建用户表user,并创建对应的实体类User。

image-20250421212934118

//User类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private Integer id;private String username;private String password;private String name;private Integer age;
}

3). 配置Mybatis

application.properties 中配置数据库的连接信息,数据库连接四要素,只需定义一次。

#数据库访问的url地址
spring.datasource.url=jdbc:mysql://localhost:3306/web01
#数据库驱动类类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#访问数据库-用户名
spring.datasource.username=root
#访问数据库-密码
spring.datasource.password=root@0524

上述的配置,可以直接复制过去,不要敲错了。 全部都是 spring.datasource.xxxx 开头。

4). 编写Mybatis程序:编写Mybatis的持久层接口,定义SQL语句(注解)

在创建出来的springboot工程中,在引导类所在包下,在创建一个包 mapper 。在 mapper 包下创建一个接口 UserMapper ,这是一个持久层接口(Mybatis的持久层接口规范一般都叫 XxxMapper,也叫做Mapper接口)。

UserMapper接口的内容如下:

import com.cyanm.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper  // 应用程序在运行时,会自动的为该接口创建一个实现类对象(动态代理对象),并且会自动地将该实现类对象存入IOC容器中 - bean
public interface UserMapper {@Select("select * from user")public List<User> findAll();
}

注解说明:

  • @Mapper注解:表示是mybatis中的Mapper接口

程序运行时,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理

  • @Select注解:代表的就是select查询,用于书写select查询语句

5). 单元测试

在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。

该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。

测试类代码如下:

import com.cyanm.mapper.UserMapper;
import com.cyanm.pojo.User;
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 // SpringBoot中单元测试的注解 - 当前测试类中的测试方法运行时,会启动springboot项目 - IOC容器就创建好了
class SpringbootMybatisQuickstartApplicationTests {//注入UserMapper对象@Autowiredprivate UserMapper userMapper;@Testvoid contextLoads() {//调用方法List<User> userList = userMapper.findAll();userList.forEach(System.out::println);}
}

运行结果:

注意:测试类所在包,需要与引导类/启动类所在包相同。

image-20250421215529711

image-20250421215025356

Spring Boot的包扫描机制

Spring Boot的核心特性之一是其自动配置和组件扫描机制。在应用启动时,Spring Boot会根据引导类的位置进行包扫描。具体来说:

  • 扫描范围:Spring Boot会从引导类所在的包开始,递归扫描该包及其所有子包。
  • 扫描目标:扫描过程中,Spring Boot会查找并注册所有带有特定注解的类,例如:
    • @Component(及其派生注解,如@Service@Repository@Controller等)
    • @Mapper(MyBatis中用于标记Mapper接口的注解)
    • 其他Spring支持的注解
  • 目的:通过这种机制,Spring Boot能够自动将这些类注册为Spring容器中的Bean,从而在应用运行时可以直接注入和使用。

例如,如果引导类位于com.example.demo包中,Spring Boot会扫描com.example.demo及其子包(如com.example.demo.mappercom.example.demo.service等),但不会扫描com.example.test这样的外部包。


3.1.2 辅助配置
3.1.2.1 配置SQL提示

默认我们在UserMapper接口上加的 @Select 注解中编写SQL语句是没有提示的。 如果想让idea给我们提示对应的SQL语句,我们需要在IDEA中配置与MySQL数据库的链接。

默认我们在UserMapper接口上的 @Select 注解中编写SQL语句是没有提示的。如果想让idea给出提示,可以做如下配置:

配置完成之后,发现SQL语句中的关键字有提示了,但还存在不识别表名(列名)的情况:

  • 产生原因:Idea和数据库没有建立连接,不识别表信息

  • 解决方案:在Idea中配置MySQL数据库连接

按照如下方如下方式,来配置当前IDEA关联的MySQL数据库(必须要指定连接的是哪个数据库)。

在配置的时候指定连接那个数据库,如上图所示连接的就是mybatis数据库(自己的数据库名是什么就指定什么)。

注意:该配置的目的,仅仅是为了在编写SQL语句时,有语法提示(写错了会报错),不会影响运行,即使不配置也是可以的。

3.1.2.2 配置Mybatis日志输出

默认情况下,在Mybatis中,SQL语句执行时,我们并看不到SQL语句的执行日志。 在application.properties加入如下配置,即可查看日志:

#mybatis的配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

打开上述开关之后,再次运行单元测试,就可以看到控制台输出的SQL语句是什么样子的。

3.1.3 JDBC VS Mybatis

JDBC程序的缺点

  • url、username、password 等相关参数全部硬编码在java代码中。

  • 查询结果的解析、封装比较繁琐。

  • 每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。 频繁的获取连接、释放连接造成资源浪费。

分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:

  • 数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中,配置文件不用重新编译

  • 查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注

  • 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。

使用SpringBoot+Mybatis的方式操作数据库,能够提升开发效率、降低资源浪费

而对于Mybatis来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:

  1. application.properties
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/web01
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234-
  • Mapper接口(编写SQL语句)
@Mapper
public interface UserMapper {@Select("select * from user")public List<User> list();
}
3.1.4 数据库连接池

在前面我们所讲解的mybatis中,使用了数据库连接池技术,避免频繁的创建连接、销毁连接而带来的资源浪费。

下面我们就具体的了解下数据库连接池。

3.1.4.1 介绍

1). 没有数据库连接池的情况

客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后又需要关闭连接对象从而释放资源,每次执行SQL时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。

2). 有数据库连接池的情况

数据库连接池是个容器,负责分配、管理数据库连接(Connection)

  • 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象

允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

  • 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)

释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

  • 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

数据库连接池的好处:

  • 资源重用

  • 提升系统响应速度

  • 避免数据库连接遗漏

3.1.4.2 产品

要怎么样实现数据库连接池呢?

  • 官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)

  • 功能:获取连接

    public Connection getConnection() throws SQLException;
    
  • 第三方组织必须按照DataSource接口实现

常见的数据库连接池:C3P0 、DBCP 、Druid 、Hikari (springboot默认)

现在使用更多的是:Hikari、Druid (性能更优越)

1). Hikari(追光者) [默认的连接池]

从控制台输出的日志,我们也可以看出,springboot底层默认使用的数据库连接池就是 Hikari。

2). Druid(德鲁伊)

  • Druid连接池是阿里巴巴开源的数据库连接池项目

  • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:

参考官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

①. 在pom.xml文件中引入依赖

<dependency><!-- Druid连接池依赖 --><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.19</version>
</dependency>

②. 在application.properties中引入数据库连接配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/web
spring.datasource.druid.username=root
spring.datasource.druid.password=1234

配置完毕之后,我们再次运行单元测试,大家会看到控制台输出的日志中,已经将连接池切换为了 Druid连接池。


3.1.5 增删改查操作
3.1.5.1 删除
  • 需求:根据ID删除用户信息

  • SQL:delete from user where id = 5;

  • Mapper接口方法:

    • 方式一:
    /*** 根据id删除*/
    @Delete("delete from user where id = 5")
    public void deleteById();
    

这种方式执行删除操作,调用deleteById方法只能删除id为5的用户信息,因为将id直接写死在代码中了,不可取。

在Mybatis中,我们可以通过参数占位符号 #{...} 来占位,在调用deleteById方法时,传递的参数值,最终会替换占位符。

@Delete("delete from user where id = #{id}")
public void deleteById(Integer id);
  • 编写单元测试方法进行测试

    在单元测试类中,增加如下测试方法.

    @Test
    public void testDeleteById(){userMapper.deleteById(36);
    }
    

运行单元测试,结果如下:

运行之后,我们发现,#{...} 占位符,其实最终被替换成了**?占位符** ,生成的是预编译的SQL语句。【推荐】

  • DML语句执行完毕,是有返回值的,我们可以为Mapper接口方法定义返回值来接收,如下:

    /*** 根据id删除*/
    @Delete("delete from user where id = #{id}")
    public Integer deleteById(Integer id);
    

Integer类型的返回值,表示DML语句执行完毕影响的记录数。

  • Mybatis的提供的符号,有两个,一个是 #{...},另一个是 ${...},区别如下:

    image-20250421224804148
符号作用用法说明安全性性能
#{...}预编译参数占位符将参数值通过 JDBC 的 PreparedStatement 设置到 SQL 中,使用预编译方式防止 SQL 注入。高(因为使用了预编译)
${...}字符串替换占位符将参数值直接拼接到 SQL 字符串中,不进行预编译,适用于动态表名、列名等场景,但容易引发 SQL 注入问题。低(不进行预编译,直接拼接)

那在企业项目开发中,强烈建议使用 #{…} 。

预编译原理:MyBatis 使用 #{...} 进行预编译时,会将 SQL 语句和参数分开处理。这样,MyBatis 会把参数值绑定到 SQL 语句中的占位符,而不会直接插入到 SQL 语句的结构中(例如表名、列名、运算符等)。这意味着,#{...} 只能用于动态值(如字符串、数字等),而不能修改 SQL 的结构。


3.1.5.2 新增
  • 需求:添加一个用户

  • SQL:insert into user(username,password,name,age) values(‘zhouyu’,‘123456’,‘周瑜’,20);

  • Mapper接口:

/*** 添加用户*/
@Insert("insert into user(username,password,name,age) values(#{username},#{password},#{name},#{age})")
public void insert(User user);

如果在SQL语句中,我们需要传递多个参数,我们可以把多个参数封装到一个对象中。然后在SQL语句中,我们可以通过#{对象属性名}的方式,获取到对象中封装的属性值。注意不是字段名

  • 单元测试:

在测试类中添加测试方法,代码如下:

@Test
public void testInsert(){User user = new User();user.setUsername("admin");user.setPassword("123456");user.setName("管理员");user.setAge(30);userMapper.insert(user);
}

运行结果如下:


3.1.5.3 修改
  • 需求:根据ID更新用户信息

  • SQL:update user set username = ‘zhouyu’, password = ‘123456’, name = ‘周瑜’, age = 20 where id = 1;

  • Mapper接口方法:注意是属性名!!!跟字段名没关系

/*** 根据id更新用户信息*/
@Update("update user set username = #{username},password = #{password},name = #{name},age = #{age} where id = #{id}")
public void update(User user);
  • 单元测试:

在测试类中添加测试方法,代码如下:

@Test // 全参构造也可以
public void testUpdate(){User user = new User();user.setId(6);user.setUsername("admin666");user.setPassword("123456");user.setName("管理员");user.setAge(30);userMapper.update(user);
}

运行结果如下:


3.1.5.4 查询(带条件)
  • 需求:根据用户名和密码查询用户信息

  • SQL:select * from user where user name = ‘zhouyu’ and password = ‘123456’;

  • Mapper接口方法:

/*** 根据用户名和密码查询用户信息*/
@Select("select * from user where username = #{username} and password = #{password}") //注意这里是为形参起的名字而不是方法形参名称
public User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);

@param注解的作用是为接口的方法形参起名字的。(由于用户名唯一的,所以查询返回的结果最多只有一个,可以直接封装到一个对象中)

在默认的情况下,Java 编译器会去除方法参数的名称,只保留参数的类型。这意味着编译后的字节码中可能没有方法参数的原始名字(例如 usernamepassword),因此 MyBatis 无法直接通过这些参数名称来引用它们。之前增删改只有一个形参,现在不止一个形参

  • 单元测试:

在测试类中添加测试方法,代码如下:

@Test
public void testFindByUsernameAndPassword(){User user = userMapper.findByUsernameAndPassword("admin666", "123456");System.out.println(user);
}

运行结果如下:

image-20250421234601767

说明:基于官方骨架创建的springboot项目中,接口编译时会保留方法形参名,@Param注解可以省略 (#{形参名})。

这里直接写形参名即可

如果用阿里框架还不给起名字,报错如下

字节码文件:形参名没有被保留,只保留类型

image-20250421234736514

起了名字之后的字节码文件

image-20250421234904963

注意报错不要从上往下读,直接找Caused by

image-20250421234721900

image-20250421234938104


3.1.6 XML映射配置

Mybatis的开发有两种方式:

  1. 注解: 如@Select @Update等等

  2. XML

3.1.6.1 XML配置文件规范

使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

image-20250421235320303

在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

  1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下**(同包同名)**

  2. XML映射文件的namespace属性为Mapper接口全限定名一致

  1. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致(注意是单条返回类型)。

<select>标签:就是用于编写select查询语句的。

  • resultType属性,指的是查询返回的单条记录所封装的类型。
  • id属性:这个sql语句的唯一标识,且与方法名命名一致
3.1.6.2 XML配置文件实现

第1步: 创建XML映射文件

这里不要用 .

第2步:编写XML映射文件

xml映射文件中的dtd约束,直接从mybatis官网复制即可; 或者直接AI生成。这个是固定的,不用记

官方:https://mybatis.net.cn/getting-started.html

image-20250421235646668

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

第3步:配置

a. XML映射文件的namespace属性为Mapper接口全限定名

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

b. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper"><!--查询操作--><select id="findAll" resultType="com.itheima.pojo.User">select * from user</select></mapper>

resultType 属性的值,与查询返回的单条记录封装的类型一致。

运行测试类,执行结果:

image-20250422000924130

匹配规则

  1. 一旦调用了UserMapper中的方法,就会去查询要执行的sql语句在哪个映射文件中定义,就回去查找哪份XML文件的namesapce属性是我Mapper接口的全类名,进行匹配
  2. 一份XML文件中可以有多条sql语句,那我们怎么知道调用那条呢?
    根据方法名和id名匹配来调用,

注意:一个接口方法对应的SQL语句,要么使用注解配置,要么使用XML配置,切不可同时配置。

开发规范

image-20250422001134894


3.1.6.3 MybatisX的使用

1. 指定配置XML映射文件位置

mybatis.mapper-locations=classpath:mapper/*.xml

java目录和resources目录在编译后都会放在class目录下,所以先指定一下最后位置


2.MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。

MybatisX的安装:

可以通过MybatisX快速定位:

MybatisX的使用在后续学习中会继续分享。

  • 学习了Mybatis中XML配置文件的开发方式了,大家可能会存在一个疑问:到底是使用注解方式开发还是使用XML方式开发?

官方说明:https://mybatis.net.cn/getting-started.html。下面是官方说明:

结论:使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。


4. SpringBoot配置文件

4.1 介绍

前面我们一直使用springboot项目创建完毕后自带的application.properties进行属性的配置,而如果在项目中,我们需要配置大量的属性,采用properties配置文件这种 key=value 的配置形式,就会显得配置文件的层级结构不清晰,也比较臃肿。

那其实呢,在springboot项目当中是支持多种配置方式的,除了支持properties配置文件以外,还支持另外一种类型的配置文件,就是我们接下来要讲解的yml格式的配置文件。yml格式配置文件名字为:application.yaml , application.yml 这两个配置文件的后缀名虽然不一样,但是里面配置的内容形式都是一模一样的。

我们可以来对比一下,采用 application.propertiesapplication.yml 来配置同一段信息(数据库连接信息),两者之间的配置对比:yml格式冗余部分简洁化了

在项目开发中,我们推荐使用application.yml配置文件来配置信息,简洁、明了、以数据为中心。

4.2 语法

简单的了解过springboot所支持的配置文件,以及不同类型配置文件之间的优缺点之后,接下来我们就来了解下yml配置文件的基本语法:

  • 大小写敏感
  • key和value用冒号分开,但value前必须有空格,作为分隔符
  • 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格,所以正常用)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略

了解完yml格式配置文件的基本语法之后,接下来我们再来看下yml文件中常见的数据格式。在这里我们主要介绍最为常见的两类:

  1. 定义对象或Map集合

  2. 定义数组、list或set集合

  • 对象/Map集合
user:name: zhangsanage: 18password: 123456
  • 数组/List/Set集合 -后面加各个元素的值
hobby: - java #元素1- game #元素2- sport #元素3

在yml格式的配置文件中,如果配置项的值是以 0 开头的,值需要使用 ‘’ 引起来,因为以0开头在yml中表示8进制的数据。

4.3 案例

熟悉完了yml文件的基本语法后,我们修改下之前案例中使用的配置文件,变更为application.yml配置方式:

  1. 修改application.properties名字为:_application.properties(名字随便更换,只要加载不到即可)

  2. 创建新的配置文件: application.yml

  • 原有的 application.properties 配置文件

  • 新建的 application.yml 配置文件

配置文件的内容如下:

#数据源配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/web01username: rootpassword: root@1234
#mybatis配置
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

image-20250422003700963


求关注2

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

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

相关文章

力扣-240.搜索二维矩阵 II

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, in…

Spark-Streaming(三)

一. kafka和flume的整合 任务需求一:利用flume监控某目录中新生成的文件&#xff0c;将监控到的变更数据发送给kafka&#xff0c;kafka将收到的数据打印到控制台 1. 在flume/conf/目录下添加flume-kafka.conf文件 配置文件如下 2. 启动flume和kafka消费者 3. 传入数据 查看fl…

Spring Boot 启动生命周期详解

Spring Boot 启动生命周期详解 1. 启动阶段划分 Spring Boot 启动过程分为 4个核心阶段&#xff0c;每个阶段涉及不同的核心类和执行逻辑&#xff1a; 阶段 1&#xff1a;预初始化&#xff08;Pre-initialization&#xff09; 目标&#xff1a;准备启动器和环境配置关键类&am…

《深入理解 AOP》

一、AOP 是什么 AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff0c;即面向切面编程&#xff0c;是软件开发中一种重要的编程范式。它通过横向抽取机制&#xff0c;将那些与业务逻辑本身无关、却为业务模块所共同调用的逻辑或责任&#xff08;如事务处理、日…

Python【协程(Coroutine)和线程的关系】

协程(Coroutine)和线程都是实现并发编程的技术&#xff0c;但它们在实现方式、使用场景和性能上有显著区别。理解它们的关系与差异有助于在实际应用中选择合适的并发模型&#xff0c;以下是它们的核心关系与对比分析&#xff1a; 一、核心关系 互补关系 协程和线程可以结合使用…

Springboot——Redis的使用

在当今的软件开发领域&#xff0c;缓存技术是提升应用性能的关键手段之一。Redis 作为一款高性能的键值对存储数据库&#xff0c;凭借其出色的读写速度和丰富的数据结构&#xff0c;在缓存场景中得到了广泛应用。Spring Boot 作为一款简化 Spring 应用开发的框架&#xff0c;与…

BEVPoolv2:A Cutting-edge Implementation of BEVDet Toward Deployment

背景 该论文是在BEVDet的基础上进行了一个调整优化&#xff0c;传统的方法是将特征图与深度预测进行外积得到视椎特征图&#xff0c;再将它与预处理好的体素索引结合&#xff0c;将每个视椎特征分类到每个voxel中进行累加和的操作。BEVFusion与BEVDepth等方法是避免了累加和&a…

蓝桥杯常考的找规律题

目录 灵感来源&#xff1a; B站视频链接&#xff1a; 找规律题具有什么样的特点&#xff1a; 报数游戏&#xff08;Java组&#xff09;&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路详解&#xff1a; 代码详解&#xff1a; 阶乘求和&#xff08;Java组…

使用ffmpeg 将图片合成为视频,填充模糊背景,并添加两段音乐

1.输入3张图片,每张播放一次,播放两秒,视频分辨率设置为1920:1080,每张图片前0.3秒淡入,后0.3秒淡出,图片宽高比不变,用白色填充空白区域 ffmpeg -loop 1 -t 2 -i "img1.jpg" \-loop 1 -t 2 -i "img2.jpg" \-loop 1 -t 2 -i "img3.jpg" \-filte…

PostgreSQL技术内幕29:事件触发器tag原理解析

文章目录 0.简介1.概念说明2.tag的生成和存储2.1 tag合法性校验2.2 内存中存储2.3 持久化存储 3.tag的触发 0.简介 在上一篇文章中中&#xff0c;我们介绍了PG中的两种触发器&#xff0c;即适合于DML的普通触发器和对于DDL的事件触发器&#xff0c;其中事件触发器与常规的 DML…

mysql 导入很慢,如何解决

精选 原创 码出财富2025-04-14 17:35:14博主文章分类&#xff1a;数据库©著作权 文章标签mysql数据库用户名文章分类MySQL数据库yyds干货盘点阅读数184 导入大型 SQL 文件到 MySQL 数据库时&#xff0c;速度可能会受到影响。以下是一些优化方法和建议&#xff0c;帮助你…

多物理场耦合低温等离子体装置求解器PASSKEy2

文章目录 PASSKEy2简介PASSKEY2计算流程PASSKEy2 中求解的物理方程电路模型等离子体模型燃烧模型 PASSKEy2的使用 PASSKEy2简介 PASSKEy2 是在 PASSKEy1 的基础上重新编写的等离子体数值模拟程序。 相较于 PASSKEy1&#xff0c; PASSKEy2 在具备解决低温等离子体模拟问题的能力…

保姆级zabbix监控jmx、数据库和网络监控(SNMP)

前言 在当今数字化时代&#xff0c;企业IT基础设施的稳定性与性能直接关系到业务连续性和用户体验。随着系统复杂性的不断增加&#xff0c;单一维度的监控已难以满足全面运维需求。Zabbix作为一款功能强大的开源监控解决方案&#xff0c;通过整合JMX&#xff08;Java Manageme…

复杂地形越野机器人导航新突破!VERTIFORMER:数据高效多任务Transformer助力越野机器人移动导航

作者&#xff1a; Mohammad Nazeri 1 ^{1} 1, Anuj Pokhrel 1 ^{1} 1, Alexandyr Card 1 ^{1} 1, Aniket Datar 1 ^{1} 1, Garrett Warnell 2 , 3 ^{2,3} 2,3, Xuesu Xiao 1 ^{1} 1单位&#xff1a; 1 ^{1} 1乔治梅森大学计算机科学系&#xff0c; 2 ^{2} 2美国陆军研究实验室&…

SharpMap与TerraLib:C#与C++开源GIS库

大家好&#xff0c;今天为大家介绍的软件是SharpMap&#xff1a;一款专为了C#&#xff08;.NET&#xff09;环境设计的开源地图和空间数据处理库&#xff1b;TerraLib&#xff1a;一款由C编写、支持多种数据库的开源的GIS软件库。 下面&#xff0c;我们将从两个开源软件的主要…

音视频学习 - MP3格式

环境 JDK 13 IDEA Build #IC-243.26053.27, built on March 16, 2025 Demo MP3Parser MP3 MP3全称为MPEG Audio Layer 3&#xff0c;它是一种高效的计算机音频编码方案&#xff0c;它以较大的压缩比将音频文件转换成较小的扩展名为.mp3的文件&#xff0c;基本保持源文件的音…

Unity中数据和资源加密(异或加密,AES加密,MD5加密)

在项目开发中&#xff0c;始终会涉及到的一个问题&#xff0c;就是信息安全&#xff0c;在调用接口&#xff0c;或者加载的资源&#xff0c;都会涉及安全问题&#xff0c;因此就出现了各种各样的加密方式。 常见的也是目前用的最广的加密方式&#xff0c;分别是&#xff1a;DE…

部署本地deepseek并在调用的详细步骤以及解决一些可能出现的问题(Windows,Linux, WSL)

打开Ollama官网&#xff1a;https://ollama.com/ 直接下载Ollama并且安装好Ollama、这时候就能看到app里多了个ollama&#xff0c;但是我们不用打开它 打开Windows Powershell&#xff1a; ollama run deepseek-r1:1.5b 7b 8b 14b 32b 70b 根据自己的电脑配置和需求更换不同的…

【KWDB 创作者计划】_嵌入式硬件篇---寄存器与存储器截断与溢出

文章目录 前言一、寄存器与存储器1. 定义与基本概念寄存器(Register)位置功能特点存储器(Memory)位置功能特点2. 关键区别3. 层级关系与协作存储层次结构协作示例4. 为什么需要寄存器性能优化指令支持减少总线竞争5. 其他寄存器类型专用寄存器程序计数器(PC)栈指针(SP)…

小白自学python第二天

学习python的第二天 一、判断语句 1、布尔类型和比较运算符 1、布尔类型 表示现实生活中的逻辑&#xff0c;真&#xff08;True&#xff0c;用数字1表示&#xff09;和假&#xff08;False&#xff0c;用数字0表示&#xff09; 2、布尔类型变量的定义 变量的名称 布尔类…