Java Web JDBC(2)23.6.26

news2024/11/13 9:08:45

3.6 PreparedStatement

PreparedStatement作用:

  • 预编译SQL语句并执行:预防SQL注入问题

3.6.1 代码模拟SQL注入问题

@Test
public void testLogin() 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 = "sjdljfld";
    String pwd = "' or '1' = '1";
    String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
    // 获取stmt对象
    Statement stmt = conn.createStatement();
    // 执行sql
    ResultSet rs = stmt.executeQuery(sql);
    // 判断登录是否成功
    if(rs.next()){
        System.out.println("登录成功~");
    }else{
        System.out.println("登录失败~");
    }

    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

上面代码是将用户名和密码拼接到sql语句中,拼接后的sql语句如下

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

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

接下来我们来学习PreparedStatement对象.

3.6.2 PreparedStatement概述

PreparedStatement作用:

  • 预编译SQL语句并执行:预防SQL注入问题
  • 获取 PreparedStatement 对象

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

    上面的sql语句中参数使用 ? 进行占位,在之前之前肯定要设置这些 ? 的值。

    PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值

    • Xxx:数据类型 ; 如 setInt (参数1,参数2)

    • 参数:

      • 参数1: ?的位置编号,从1 开始

      • 参数2: ?的值

  • 执行SQL语句

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

    executeQuery(); 执行DQL语句

    注意:

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

3.6.3 使用PreparedStatement改进

 @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";

    // 定义sql
    String sql = "select * from tb_user where username = ? and password = ?";
    // 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);
    // 设置?的值
    pstmt.setString(1,name);
    pstmt.setString(2,pwd);
    // 执行sql
    ResultSet 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'

3.6.4 PreparedStatement原理

PreparedStatement 好处:

  • 预编译SQL,性能更高
  • 防止SQL注入:将敏感字符进行转义

请添加图片描述

Java代码操作数据库流程如图所示:

  • 将sql语句发送到MySQL服务器端

  • MySQL服务端会对sql语句进行如下操作

    • 检查SQL语句

      检查SQL语句的语法是否正确。

    • 编译SQL语句。将SQL语句编译成可执行的函数。

      检查SQL和编译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
    
  • java测试代码如下:

     /**
       * PreparedStatement原理
       * @throws Exception
       */
    @Test
    public void testPreparedStatement2() throws  Exception {
    
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        // useServerPrepStmts=true 参数开启预编译功能
        String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true";
        String username = "root";
        String password = "1234";
        Connection conn = DriverManager.getConnection(url, username, password);
    
        // 接收用户输入 用户名和密码
        String name = "zhangsan";
        String pwd = "' or '1' = '1";
    
        // 定义sql
        String sql = "select * from tb_user where username = ? and password = ?";
    
        // 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
    
        Thread.sleep(10000);
        // 设置?的值
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);
        ResultSet rs = null;
        // 执行sql
        rs = pstmt.executeQuery();
    
        // 设置?的值
        pstmt.setString(1,"aaa");
        pstmt.setString(2,"bbb");
        // 执行sql
        rs = pstmt.executeQuery();
    
        // 判断登录是否成功
        if(rs.next()){
            System.out.println("登录成功~");
        }else{
            System.out.println("登录失败~");
        }
    
        //7. 释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
    
  • 执行SQL语句,查看 D:\mysql.log 日志如下:

请添加图片描述

上图中第三行中的 Prepare 是对SQL语句进行预编译。第四行和第五行是执行了两次SQL语句,而第二次执行前并没有对SQL进行预编译。

小结:

  • 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
  • 执行时就不用再进行这些步骤了,速度更快
  • 如果sql模板一样,则只需要进行一次检查、编译

4,数据库连接池

4.1 数据库连接池简介

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

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

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

  • 好处

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

之前我们代码中使用连接是没有使用都创建一个Connection对象,使用完毕就会将其销毁。这样重复创建销毁的过程是特别耗费计算机的性能的及消耗时间的。

而数据库使用了数据库连接池后,就能达到Connection对象的复用,如下图

请添加图片描述

连接池是在一开始就创建好了一些连接(Connection)对象存储起来。用户需要连接数据库时,不需要自己创建连接,而只需要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池;这样就可以起到资源重用,也节省了频繁创建连接销毁连接所花费的时间,从而提升了系统响应的速度。

4.2 数据库连接池实现

  • 标准接口:DataSource

    官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。该接口提供了获取连接的功能:

    Connection getConnection()
    

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

  • 常见的数据库连接池

    • DBCP
    • C3P0
    • Druid

    我们现在使用更多的是Druid,它的性能比其他两个会好一些。

  • Druid(德鲁伊)

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

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

4.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. 获取数据库连接 Connection
        Connection connection = dataSource.getConnection();
        System.out.println(connection); //获取到了连接后就可以继续做其他操作了

        //System.out.println(System.getProperty("user.dir"));
    }
}

5,JDBC练习

5.1 需求

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

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

5.2 案例实现

5.2.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;
        }
    
        @Override
        public 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. 获取数据库连接 Connection
    Connection conn = dataSource.getConnection();
    //2. 定义SQL
    String sql = "select * from tb_brand;";
    //3. 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);
    //4. 设置参数
    //5. 执行SQL
    ResultSet 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. 获取数据库连接 Connection
    Connection conn = dataSource.getConnection();
    //2. 定义SQL
    String 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. 执行SQL
    int count = pstmt.executeUpdate(); // 影响的行数
    //6. 处理结果
    System.out.println(count > 0);

    //7. 释放资源
    pstmt.close();
    conn.close();
}

5.2.4 修改数据

/**
  * 修改
  * 1. SQL:

     update tb_brand
         set 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. 获取数据库连接 Connection
    Connection conn = dataSource.getConnection();
    //2. 定义SQL
    String 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. 执行SQL
    int 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. 获取数据库连接 Connection
    Connection conn = dataSource.getConnection();
    //2. 定义SQL
    String sql = " delete from tb_brand where id = ?";
    //3. 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);
    //4. 设置参数
    pstmt.setInt(1,id);
    //5. 执行SQL
    int count = pstmt.executeUpdate(); // 影响的行数
    //6. 处理结果
    System.out.println(count > 0);

    //7. 释放资源
    pstmt.close();
    conn.close();
}

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

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

相关文章

浅谈无线温度监测系统在冶炼厂供配电的应用

安科瑞 华楠 摘要&#xff1a;高压供配电系统运行稳定性与电气元器件连接点温度密切相关&#xff0c;通过与传统测温方法对比&#xff0c;实时在线无线温度监测解决 了密封高压开关柜内部各连接点温度无法检测的难题&#xff0c;满足了供电系统安全稳定运行的要求&#xff0c;降…

redis 主从复制 哨兵 安装部署

学习开始前先了解一下 Redis是一个开源的内存数据结构存储系统&#xff0c;它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等。Redis最大的特点是数据存储在内存中&#xff0c;因此读写速度非常快&#xff0c;同时也支持数据持久化&#xff0c;可以将数…

吐血整理,接口自动化测试-Config配置文件框架封装(实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 configparser的介…

阿里巴巴2023最新版Spring Security王者晋级文档

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 是 Spring 家族中的一个安全管理框架&#xff0c;提供了一套 Web 应用安全性的完整解决方案。在用户认证方面&#xff0c;Spring Security 框架支持主流的认证方式&#xff0c;包括 HTTP 基本认证、HTTP 表单…

输出一个数的十六进制表示

可以使用Integer.toHexString、Long.toHexString得到数值的十六进制表示。 下面的代码示例列出了几种情况&#xff1a; public class Test5 {public static void main(String[] args) {byte b1 0b01101111; System.out.println(Integer.toHexString(b1).toUpperCase());byte…

深度学习的实践层面

目录 1、训练、验证、测试集 2、偏差、方差 3、正则化 4、dropoout正则化 5、其他正则化方法 6、归一化输入 7、梯度消失和梯度爆炸 8、梯度的数值逼近 9、梯度检验 1、训练、验证、测试集 &#xff08;1&#xff09;、早期机器学习领域普遍认可的最好的实践方法&…

海兰一体机电脑U盘重装Win10系统教程图解

海兰一体机电脑是全家人都适用的电脑&#xff0c;使用海兰一体机电脑的用户要怎么用U盘来重装Win10系统&#xff0c;首先用户需要确保电脑能够正常联网&#xff0c;然后再准备一个8G以上的U盘&#xff0c;最后根据小编分享的海兰一体机电脑U盘重装Win10系统教程图解操作即可。 …

PR脚本:音乐鼓点自动节拍打点标记动画BeatEdit

BeatEdit可检测音乐中的节拍并在Premiere Pro时间轴中为其生成标记。可以创建与音乐同步的自动编辑&#xff0c;或者让BeatEdit v2.0.006 激活版协助您进行手动编辑过程。BeatEdit mac版使用节拍信息来生成与音乐同步的全自动编辑。如果需要更多控制&#xff0c;拍子标记也可以…

视唱音准不好的人能练好吗,视唱音准不好怎么办

软件版本&#xff1a;Earmaster7.3.6 无论是普通人还是声乐艺术生&#xff0c;音准是唱好歌的必要条件之一&#xff0c;如果音准不好&#xff0c;唱歌自然会跑调。然而并不是所有人天生都有十分出色的音准&#xff0c;如果不进行后天的训练&#xff0c;是很难找到正确的音准的…

web应用封装成app|超级签名

PP封装是形成APP的最省钱的一种方式。你只需要拥有一个网址就可以通过一些技术处理封装成一个跨iOS和Android的APP&#xff0c;这个过程往往只需要几分钟。在移动互联网时代&#xff0c;拥有一个移动端APP是必不可少的。那么APP是怎样封装的呢&#xff1f; 首先让我们先来了解…

基于深度学习的人脸面部表情识别系统【含Python源码+PyqtUI界面+原理详解】

功能演示 摘要&#xff1a;面部表情识别&#xff08;Facial Expression Recognition&#xff09;是一种通过技术手段识别人物图像中人脸面部表情的技术。本文详细介绍了其实现的技术原理&#xff0c;同时给出完整的Python实现代码、训练好的深度学习模型&#xff0c;并且通过Py…

Python中的四种条件语句结构和应用举例

Python中的四种条件语句结构和应用举例 条件语句是计算机实现分类高效执行计算的重要方法。在许多计算机语言编写&#xff08;C语言&#xff0c;Java语言&#xff0c;matlab语言等&#xff09;的时候&#xff0c;都有涉及条件语句的部分&#xff0c;本文对Python语言中的条件语…

Docker操作镜像与容器常用命令

Docker操作镜像与容器的常用命令 文章目录 Docker操作镜像与容器的常用命令前言1、镜像相关命令1.1 查看镜像1.2 搜索镜像1.3 拉取镜像1.4 删除镜像 2 容器相关命令2.1 查看容器2.2 创建与启动容器2.3 停止与启动容器2.4 文件拷贝2.5 目录挂载2.6 查看容器IP地址2.7 删除容器 总…

金山云联合MiniMax推出MaaS互信推理专区方案 解决大模型与数据互信难题

作为人工智能领域颇具里程碑式的进展&#xff0c;ChatGPT以其惊艳的表现&#xff0c;迅速掀起了行业热潮&#xff0c;使得大模型成为当下最为炙手可热的技术方向之一。但在大模型落地过程中&#xff0c;如何既能保障大模型使用方的数据安全&#xff0c;又能保护大模型提供方的部…

C编译过程 以及 ELF文件(学习笔记)

C编译过程 一个用C语言编写的高级语言程序是从编写到打包、再到编译执行的基本过程&#xff0c;我们知道在CPU上执行的是低级别的机器语言&#xff0c;从高级语言到低级别的机器语言肯定是要经过翻译过程&#xff0c;这个过程大体的过程如下图所示: 在Unix系统中&#xff0c;从…

基于simulink的四节串联锂电池的主动均衡算法(PID控制)

电动汽车往往搭载上百节单体电池作为能量来源,如此多的电池聚在一起其性能差异往往造成电量的不一致。不均衡性会随着电池的充放电循环而不断加剧,致使单体容量快速衰减&#xff0c;最终个别单体的失效就会影响整个电池组乃至用电系统的工作。常见的均衡方式可分为主动均衡和被…

亚马逊云科技“专库专用”模式,可有效提高数据库的性能和效率

近日&#xff0c;全球数据库市场发生了一件令人瞩目的事件&#xff0c;根据Gartner的数据&#xff0c;我们发现亚马逊云科技作为一个纯云厂商&#xff0c;夺得了2022年全球数据库领导者的桂冠&#xff0c;占据全球市场的25.3%份额。 云原生数据库的发展方向&#xff1a;与数据分…

深度剖析PostgreSQL慢SQL:原因与优化方案大揭秘

​ PostgreSQL 是一种成熟稳定的关系型数据库管理系统&#xff0c;它支持高级的数据类型、索引以及查询语言。但是&#xff0c;尽管 PostgreSQL 在性能和可靠性方面表现出色&#xff0c;但偶尔也会出现慢 SQL 的情况。本文将探讨 PostgreSQL 慢 SQL 的原因和优化方案&#xff0…

Qt安卓AMD64-v8a配置OpenCV4.5.2

1.OpenCV官方网下载OpenCV的安卓平台SDK并解压 在工程的配置pro文件中添加opencv包含路径INCLUDEPATH与库LIBS unix {ANDROID_OPENCV = C:\Users\dev2\Desktop\OpenCV-android-sdk\sdk\nativeINCLUDEPATH += $$ANDROID_OPENCV/jni/include/opencv2 \$$ANDROID_OPENCV/jni/in…

进行网站建设,开启数字化时代的新篇章

在当今数字化时代&#xff0c;拥有一个个人或企业网站已经成为了非常普遍的需求。网站可以帮助你展示自己或品牌的形象、提供各种服务和信息&#xff0c;甚至是进行在线销售等&#xff0c;这些都是传统媒体所无法比拟的优势。 网站建设是什么&#xff1f; 网站建设是指在互联…