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

jdbc(DriverManager+Connection+Statement+ResultSet)+SQL注入+开启预编译+数据连接池

1 JDBC概念

JDBC 就是使用Java连接并操作数据库的一套API

全称:( Java DataBase Connectivity ) Java 数据库连接

2 JDBC优势

可随时替换底层数据库,访问数据库的Java代码基本不变

以后编写操作数据库的代码只需要面向JDBC(接口),操作哪儿个关系型数据库就需要导入该数据库的驱动包,如需要操作MySQL数据库,就需要再项目中导入MySQL数据库的驱动包。

3 JDBC快速入门

第一步:编写Java代码
第二步:Java代码将SQL发送到MySQL服务端
第三步:MySQL服务端接收到SQL语句并执行该SQL语句
第四步:将SQL语句执行的结果返回给Java代码

3.1 编写代码步骤

  • 创建工程,导入驱动jar包
    将mysql的驱动包放在模块下的lib目录(随意命名)下,并将该jar包添加为库文件
    在这里插入图片描述

在这里插入图片描述

  • 在添加为库文件的时候,有如下三个选项

    • Global Library : 全局有效
    • Project Library : 项目有效
    • Module Library : 模块有效

      一般选择全局有效

  • 注册驱动

    Class.forName("com.mysql.jdbc.Driver");
    
  • 获取连接
    Java代码需要发送SQL给MySQL服务端,就需要先建立连接

    Connection conn = DriverManager.getConnection(url, username, password);
    
  • 定义SQL语句

    String sql =update…” ;
    
  • 获取执行SQL对象

    执行SQL语句需要SQL执行对象,而这个执行对象就是Statement对象

    Statement stmt = conn.createStatement();
    
  • 执行SQL

    stmt.executeUpdate(sql);  
    
  • 处理返回结果

  • 释放资源

3.2 完整代码

/*** JDBC快速入门*/
public class JDBCDemo {public static void main(String[] args) throws Exception {//1. 注册驱动//Class.forName("com.mysql.jdbc.Driver");//2. 获取连接String url = "jdbc:mysql://127.0.0.1:3306/db1";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);//3. 定义sqlString sql = "update account set money = 2000 where id = 1";//4. 获取执行sql的对象 StatementStatement stmt = conn.createStatement();//5. 执行sqlint count = stmt.executeUpdate(sql);//受影响的行数//6. 处理结果System.out.println(count);//7. 释放资源stmt.close();conn.close();}
}

3 DriverManager

DriverManager(驱动管理类)用于

  • 注册驱动

    但MySQL 5之后的驱动包,可以省略注册驱动的步骤

  • 获取数据库连接

    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…

    示例:jdbc:mysql://127.0.0.1:3306/db1

    细节:

    • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对

    • 配置 useSSL=false 参数,禁用安全连接方式,解决警告提示

4 Connection

Connection(数据库连接对象)作用:

  • 获取执行 SQL 的对象
  • 管理事务

4.1 获取执行对象

  • 普通执行SQL对象

    Statement createStatement()
    

    入门案例中就是通过该方法获取的执行对象。

  • 预编译SQL的执行SQL对象:防止SQL注入

    PreparedStatement  prepareStatement(sql)
    

    通过这种方式获取的 PreparedStatement SQL语句执行对象可以防止SQL注入。

4.2 事务管理

先回顾一下MySQL事务管理的操作:

  • 开启事务 : BEGIN; 或者 START TRANSACTION;
  • 提交事务 : COMMIT;
  • 回滚事务 : ROLLBACK;

MySQL默认是自动提交事务

接下来学习JDBC事务管理的方法。

Connection几口中定义了3个对应的方法:

  • 开启事务
    参与autoCommit 表示是否自动提交事务,true表示自动提交事务,false表示手动提交事务。而开启事务需要将该参数设为为false。
  • 提交事务
  • 回滚事务
    具体代码实现如下:
/*** JDBC API 详解:Connection*/
public class JDBCDemo3_Connection {public static void main(String[] args) throws Exception {//1. 注册驱动//Class.forName("com.mysql.jdbc.Driver");//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写String url = "jdbc:mysql:///db1?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);//3. 定义sqlString sql1 = "update account set money = 3000 where id = 1";String sql2 = "update account set money = 3000 where id = 2";//4. 获取执行sql的对象 StatementStatement stmt = conn.createStatement();try {// ============开启事务==========conn.setAutoCommit(false);//5. 执行sqlint count1 = stmt.executeUpdate(sql1);//受影响的行数//6. 处理结果System.out.println(count1);int i = 3/0;//5. 执行sqlint count2 = stmt.executeUpdate(sql2);//受影响的行数//6. 处理结果System.out.println(count2);// ============提交事务==========//程序运行到此处,说明没有出现任何问题,则需求提交事务conn.commit();} catch (Exception e) {// ============回滚事务==========//程序在出现异常时会执行到这个地方,此时就需要回滚事务conn.rollback();e.printStackTrace();}//7. 释放资源stmt.close();conn.close();}
}

5 Statement

Statement对象的作用就是用来执行SQL语句。而针对不同类型的SQL语句使用的方法也不一样。

/*** 执行DML语句* @throws Exception*/
@Test
public void testDML() throws  Exception {//1. 注册驱动//Class.forName("com.mysql.jdbc.Driver");//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写String url = "jdbc:mysql:///db1?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);//3. 定义sqlString sql = "update account set money = 3000 where id = 1";//4. 获取执行sql的对象 StatementStatement stmt = conn.createStatement();//5. 执行sqlint count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数//6. 处理结果//System.out.println(count);if(count > 0){System.out.println("修改成功~");}else{System.out.println("修改失败~");}//7. 释放资源stmt.close();conn.close();
}

6 ResultSet

6.1 概述

ResultSet(结果集对象)是用来封装SQL查询语句的结果。

而执行了DQL语句后就会返回该对象,对应执行DQL语句的方法如下:

ResultSet  executeQuery(sql):执行DQL 语句,返回 ResultSet 对象

那么我们就需要从 ResultSet 对象中获取我们想要的数据。ResultSet 对象提供了操作查询结果数据的方法,如下:

boolean next()

  • 将光标从当前位置向前移动一行
  • 判断当前行是否为有效行

6.2 代码实现

/*** 执行DQL* @throws Exception*/
@Test
public void testResultSet() throws  Exception {//1. 注册驱动//Class.forName("com.mysql.jdbc.Driver");//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写String url = "jdbc:mysql:///db1?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);//3. 定义sqlString sql = "select * from account";//4. 获取statement对象Statement stmt = conn.createStatement();//5. 执行sqlResultSet rs = stmt.executeQuery(sql);//6. 处理结果, 遍历rs中的所有数据// 6.1 光标向下移动一行,并且判断当前行是否有数据while (rs.next()){//6.2 获取数据  getXxx()int id = rs.getInt("id");String name = rs.getString("name");double money = rs.getDouble("money");System.out.println(id);System.out.println(name);System.out.println(money);System.out.println("--------------");}//7. 释放资源rs.close();stmt.close();conn.close();
}

7 SQL注入

SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

代码模拟

select * from tb_user where username = 'sjdljfld' and password = ''or '1' = '1'

从上面语句可以看出条件 username = 'sjdljfld' and password = '' 不管是否满足,而 or 后面的 '1' = '1' 是始终满足的,最终条件是成立的,就可以正常的进行登陆了。

7.1 PreparedStatement简介

PreparedStatement作用: 预编译SQL语句并执行:预防SQL注入问题。

  • 获取 PreparedStatement 对象

    // SQL语句中的参数值,使用?占位符替代
    String sql = "select * from user where username = ? and password = ?";
    // 通过Connection对象获取,并传入对应的sql语句
    PreparedStatement pstmt = conn.prepareStatement(sql);
    
  • 设置参数值

  • 执行SQL语句

    executeUpdate(); 执行DDL语句和DML语句

    executeQuery(); 执行DQL语句

    注意:

    • 调用这两个方法时不需要传递SQL语句,因为获取SQL语句执行对象时已经对SQL语句进行预编译了。

7.2 使用PreparedStatement改进sql注入

 @Test
public void testPreparedStatement() throws  Exception {//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写String url = "jdbc:mysql:///db1?useSSL=false";String username = "root";String password = "1234";Connection conn = DriverManager.getConnection(url, username, password);// 接收用户输入 用户名和密码String name = "zhangsan";String pwd = "' or '1' = '1";// 定义sqlString sql = "select * from tb_user where username = ? and password = ?";// 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);// 设置?的值pstmt.setString(1,name);pstmt.setString(2,pwd);// 执行sqlResultSet rs = pstmt.executeQuery();// 判断登录是否成功if(rs.next()){System.out.println("登录成功~");}else{System.out.println("登录失败~");}//7. 释放资源rs.close();pstmt.close();conn.close();
}

执行上面语句就可以发现不会出现SQL注入漏洞问题了。那么PreparedStatement又是如何解决的呢?它是将特殊字符进行了转义,转义的SQL如下:

select * from tb_user where username = 'sjdljfld' and password = '\'or \'1\' = \'1'

8 开启预编译

数据库检查SQL和编译SQL花费的时间比执行SQL的时间还要长。如果我们只是重新设置参数,那么检查SQL语句和编译SQL语句将不需要重复执行。这样就提高了性能。
  • 开启预编译功能

    在代码中编写url时需要加上以下参数。而我们之前根本就没有开启预编译功能,只是解决了SQL注入漏洞。

    useServerPrepStmts=true
    
  • 配置MySQL执行日志(重启mysql服务后生效)

    在mysql配置文件(my.ini)中添加如下配置

    log-output=FILE
    general-log=1
    general_log_file="D:\mysql.log"
    slow-query-log=1
    slow_query_log_file="D:\mysql_slow.log"
    long_query_time=2
    

9 数据库连接池

9.1 简介

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

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

  • 释放超过最大空闲时间的数据库连接来避免数据库连接遗漏

  • 好处

    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏

之前我们代码中使用连接是没有使用都创建一个Connection对象,使用完毕就会将其销毁。这样重复创建销毁的过程性能很低。
而使用数据库连接池能达到Connection对象的复用.

9.2 实现

  • 标准接口:DataSource

    Connection getConnection()
    

    以后就不需要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对象。

  • 常见的数据库连接池

    • DBCP
    • C3P0
    • Druid

    我们现在使用更多的是Druid(阿里巴巴开源),它的性能比其他两个会好一些。

9.3 Driud使用

  • 导入jar包 druid-1.1.12.jar
  • 定义配置文件
  • 加载配置文件
  • 获取数据库连接池对象
  • 获取连接

现在通过代码实现,首先需要先将druid的jar包放到项目下的lib下并添加为库文件。编写配置文件如下:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

使用druid的代码如下:

/*** Druid数据库连接池演示*/
public class DruidDemo {public static void main(String[] args) throws Exception {//1.导入jar包//2.定义配置文件//3. 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));//4. 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//5. 获取数据库连接 ConnectionConnection connection = dataSource.getConnection();System.out.println(connection); //获取到了连接后就可以继续做其他操作了//System.out.println(System.getProperty("user.dir"));}
}

10 案例实现

完成商品品牌数据的增删改查操作

  • 查询:查询所有数据
  • 添加:添加品牌
  • 修改:根据id修改
  • 删除:根据id删除

9.1 环境准备

  • 数据库表 tb_brand

    -- 删除tb_brand表
    drop table if exists tb_brand;
    -- 创建tb_brand表
    create table tb_brand (-- id 主键id int primary key auto_increment,-- 品牌名称brand_name varchar(20),-- 企业名称company_name varchar(20),-- 排序字段ordered int,-- 描述信息description varchar(100),-- 状态:0:禁用  1:启用status int
    );
    -- 添加数据
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),('小米', '小米科技有限公司', 50, 'are you ok', 1);
    
  • 在pojo包下实体类 Brand

    /*** 品牌* alt + 鼠标左键:整列编辑* 在实体类中,基本数据类型建议使用其对应的包装类型*/
    public class Brand {// id 主键private Integer id;// 品牌名称private String brandName;// 企业名称private String companyName;// 排序字段private Integer ordered;// 描述信息private String description;// 状态:0:禁用  1:启用private Integer status;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrandName() {return brandName;}public void setBrandName(String brandName) {this.brandName = brandName;}public String getCompanyName() {return companyName;}public void setCompanyName(String companyName) {this.companyName = companyName;}public Integer getOrdered() {return ordered;}public void setOrdered(Integer ordered) {this.ordered = ordered;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
    }
    
5.2.2 查询所有
 /*** 查询所有* 1. SQL:select * from tb_brand;* 2. 参数:不需要* 3. 结果:List<Brand>*/@Test
public void testSelectAll() throws Exception {//1. 获取Connection//3. 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));//4. 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//5. 获取数据库连接 ConnectionConnection conn = dataSource.getConnection();//2. 定义SQLString sql = "select * from tb_brand;";//3. 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);//4. 设置参数//5. 执行SQLResultSet rs = pstmt.executeQuery();//6. 处理结果 List<Brand> 封装Brand对象,装载List集合Brand brand = null;List<Brand> brands = new ArrayList<>();while (rs.next()){//获取数据int id = rs.getInt("id");String brandName = rs.getString("brand_name");String companyName = rs.getString("company_name");int ordered = rs.getInt("ordered");String description = rs.getString("description");int status = rs.getInt("status");//封装Brand对象brand = new Brand();brand.setId(id);brand.setBrandName(brandName);brand.setCompanyName(companyName);brand.setOrdered(ordered);brand.setDescription(description);brand.setStatus(status);//装载集合brands.add(brand);}System.out.println(brands);//7. 释放资源rs.close();pstmt.close();conn.close();
}
5.2.3 添加数据
/*** 添加* 1. SQL:insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);* 2. 参数:需要,除了id之外的所有参数信息* 3. 结果:boolean*/
@Test
public void testAdd() throws Exception {// 接收页面提交的参数String brandName = "香飘飘";String companyName = "香飘飘";int ordered = 1;String description = "绕地球一圈";int status = 1;//1. 获取Connection//3. 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));//4. 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//5. 获取数据库连接 ConnectionConnection conn = dataSource.getConnection();//2. 定义SQLString sql = "insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);";//3. 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);//4. 设置参数pstmt.setString(1,brandName);pstmt.setString(2,companyName);pstmt.setInt(3,ordered);pstmt.setString(4,description);pstmt.setInt(5,status);//5. 执行SQLint count = pstmt.executeUpdate(); // 影响的行数//6. 处理结果System.out.println(count > 0);//7. 释放资源pstmt.close();conn.close();
}
5.2.4 修改数据
/*** 修改* 1. SQL:update tb_brandset brand_name  = ?,company_name= ?,ordered     = ?,description = ?,status      = ?where id = ?* 2. 参数:需要,所有数据* 3. 结果:boolean*/@Test
public void testUpdate() throws Exception {// 接收页面提交的参数String brandName = "香飘飘";String companyName = "香飘飘";int ordered = 1000;String description = "绕地球三圈";int status = 1;int id = 4;//1. 获取Connection//3. 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));//4. 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//5. 获取数据库连接 ConnectionConnection conn = dataSource.getConnection();//2. 定义SQLString sql = " update tb_brand\n" +"         set brand_name  = ?,\n" +"         company_name= ?,\n" +"         ordered     = ?,\n" +"         description = ?,\n" +"         status      = ?\n" +"     where id = ?";//3. 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);//4. 设置参数pstmt.setString(1,brandName);pstmt.setString(2,companyName);pstmt.setInt(3,ordered);pstmt.setString(4,description);pstmt.setInt(5,status);pstmt.setInt(6,id);//5. 执行SQLint count = pstmt.executeUpdate(); // 影响的行数//6. 处理结果System.out.println(count > 0);//7. 释放资源pstmt.close();conn.close();
}
5.2.5 删除数据
/*** 删除* 1. SQL:delete from tb_brand where id = ?* 2. 参数:需要,id* 3. 结果:boolean*/
@Test
public void testDeleteById() throws Exception {// 接收页面提交的参数int id = 4;//1. 获取Connection//3. 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));//4. 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//5. 获取数据库连接 ConnectionConnection conn = dataSource.getConnection();//2. 定义SQLString sql = " delete from tb_brand where id = ?";//3. 获取pstmt对象PreparedStatement pstmt = conn.prepareStatement(sql);//4. 设置参数pstmt.setInt(1,id);//5. 执行SQLint count = pstmt.executeUpdate(); // 影响的行数//6. 处理结果System.out.println(count > 0);//7. 释放资源pstmt.close();conn.close();
}

相关文章:

jdbc(DriverManager+Connection+Statement+ResultSet)+SQL注入+开启预编译+数据连接池

1 JDBC概念 JDBC 就是使用Java连接并操作数据库的一套API 全称&#xff1a;( Java DataBase Connectivity ) Java 数据库连接 2 JDBC优势 可随时替换底层数据库&#xff0c;访问数据库的Java代码基本不变 以后编写操作数据库的代码只需要面向JDBC&#xff08;接口&#xf…...

NoSQL之 Redis命令工具及常用命令

目录 1 Redis 命令工具 1.1 redis-cli 命令行工具 1.2 redis-benchmark 测试工具 2 Redis 数据库常用命令 2.1 set&#xff1a;存放数据&#xff0c;命令格式为 set key value 2.2 get&#xff1a;获取数据&#xff0c;命令格式为 get key 2.3 keys 命令可以取符合规则的…...

多线程(线程互斥)

抢票代码编写 学习了前面有关线程库的操作后&#xff0c;我们就可以模拟抢票的过程 假设我们创建四个线程&#xff0c;分别代表我们的用户 然后设定总票数为1000张&#xff0c;四个线程分别将进行循环抢票操作&#xff0c;其实就是循环对票数进行打印&#xff0c;并进行对应的…...

使用 html2canvas 和 jspdf 将页面转 pdf,同时解决当页面过长时,页面白屏问题

代码如下&#xff0c;直接粘贴复制即可&#xff0c;代码中 jspdf 是全局引入&#xff0c;你可以自己局部引入 别人使用标签的方式来显示 base64&#xff0c;但是当页面过长时&#xff0c;base64 大小过大会导致页面解析异常&#xff0c;显示白屏 import html2canvas from html2…...

【Python 千题 —— 基础篇】今年几岁啦

题目描述 题目描述 介绍自己的年龄。请使用 input 函数读入一个整数&#xff0c;表示自己的年龄&#xff0c;然后程序将自动生成介绍自己年龄的英文语句。 输入描述 输入一个整数&#xff0c;表示自己的年龄。 输出描述 程序将生成一个英文语句&#xff0c;以介绍自己的年…...

git push 失败 shallow update not allowed

问题描述&#xff1a; ~/OK62xx-linux-sdk/OK62xx-linux-kernel$ git push origin master Counting objects: 83919, done. Delta compression using up to 144 threads. Compressing objects: 100% (75697/75697), done. Writing objects: 100% (83919/83919), 232.41 MiB | …...

uniapp 在uni.scss 根据@mixin定义方法 、通过@include全局使用

在官方文档中提及到uni.scss中变量的使用&#xff0c;而我想定义方法&#xff0c;这样写css样式更方便 一、官方文档的介绍 根据官方文档我知道&#xff0c;在这面定义的变量全局都可使用。接下来我要在这里定义方法。 二、在uni.scss文件中定义方法 我在uni.scss文件中定义了…...

C++ 类和对象(一)

1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完 成。 …...

rust函数

一 、函数定义 &#xff08;一&#xff09;格式 使用fn关键字 fn是 function 的缩写 1.无返回值的 fn 函数名 ( [paraname: type]... ) {函数体 }参数必须声明参数名称和类型 函数定义时指定的参数叫做 形参。调用时传递给函数的参数叫做 实参。 例子 fn another_function(…...

链表的基本操作

&#xff08;一&#xff09;实验类型&#xff1a;设计性 &#xff08;二&#xff09;实验目的&#xff1a; 1. 掌握线性表的链式存贮结构及基本操作&#xff0c;深入了解链表的基本特性&#xff0c;以便在实际问题背景下灵活运用它们。 2. 巩固该存贮结构的构造方法&#xff0…...

Flutter AI五子棋

前言 在上一篇文章中&#xff0c;讲解了如何实现双人在本地对战的五子棋&#xff0c;但是只有一个人的时候就不太好玩&#xff0c;同时博主也没有把五子棋相关的文章写过瘾。那么这篇文章&#xff0c;我们来实现一个功能更加丰富的五子棋吧&#xff01;在设计五子棋的算法方面&…...

springboot项目中后台文件上传处理

参考地址:http://www.gxcode.top/code 文件上次核心处理代码: @Autowired private FileUpload fileUpload; //获取资源对象:file-upload-prod.properties@ApiOperation(value = "用户头像修改", notes = "用户头像修改", httpMethod =...

【SQL】MySQL中的存储引擎、事务、锁、日志

存储引擎&#xff1a; 数据库管理系统&#xff08;DBMS&#xff09;使用数据存储引擎进行创建、查询、更新和删除数据。 MySQL5.5之前默认的存储引擎是MyISAM&#xff0c;5.5及之后版本默认的存储引擎是InnoDB。(my.ini中指定的) MyISAM&#xff1a;不支持事务&#xff0c;不支…...

DRM全解析 —— CRTC详解(2)

接前一篇文章:DRM全解析 —— CRTC详解(1) 本文继续对DRM中CRTC的核心结构struct drm_crtc的成员进行释义。 3. drm_crtc结构释义 (5)struct drm_modeset_lock mutex /*** @mutex:** This provides a read lock for the overall CRTC state (mode, dpms* state, ...) an…...

3d环形图开发(vue3+vite+ts)

开发效果&#xff08;待完善&#xff09;&#xff1a; 技术支持&#xff1a; Echarts echarts-gl 安装&#xff1a; 注&#xff1a;echarts与echarts-gl版本需对应&#xff0c;可参考官网 pnpm add echarts4.9.0 echarts-gl1.1.2 组件封装&#xff1a; <template><…...

element ui中父子组件共用一个el-dialog弹窗,切换组件页面弹窗进行关闭

在Element UI中&#xff0c;如果多个父子组件共用一个el-dialog弹窗&#xff0c;并且需要在切换组件页面时关闭弹窗&#xff0c;你可以考虑以下方法来实现&#xff1a; 使用Vuex进行状态管理&#xff1a; 在Vuex中创建一个状态来管理弹窗的显示状态&#xff08;例如&#xff0…...

基于Keil a51汇编 —— Segments, Modules, and Programs

段、模块和程序 在初始设计阶段&#xff0c;定义程序要执行的任务&#xff0c;然后划分为子程序。以下是与 Ax51 汇编器和 Lx51 链接器/定位器一起使用的子程序类型的简要介绍。 段是代码块或数据存储器。段可以是可重定位的&#xff0c;也可以是绝对的。可重定位段具有名称、…...

基于Java+SpringBoot+Vue民宿管理系统的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

【Qt】三种方式实现抽奖小游戏

简介 本文章是基本Qt与C实现一个抽奖小游戏&#xff0c;用到的知识点在此前发布的几篇文章。 下面是跳转链接&#xff1a; 【Qt控件之QLabel】用法及技巧链接&#xff1a; https://blog.csdn.net/MrHHHHHH/article/details/133691441?spm1001.2014.3001.5501 【Qt控件之QPus…...

【算法与数据结构】--算法基础--算法设计与分析

一、贪心算法 贪心算法是一种解决优化问题的算法设计方法&#xff0c;其核心思想是在每一步选择当前状态下的最优解&#xff0c;从而希望最终达到全局最优解。下面将介绍贪心算法的原理、实现步骤&#xff0c;并提供C#和Java的实现示例。 1.1 原理&#xff1a; 贪心算法的原…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...