JavaWeb01-JDBC、Druid连接池

目录

一、JDBC

1.概述

2.本质

3.好处

4.使用步骤

5.JDBC_API

(1)DriverManager(驱动管理类)

(2)Connection(数据库连接对象)

(3)Statement

(4)ResultSet(结果集对象)

(5)PreparedStatement

6.使用

(1)快速上手

(2)ResultSet使用

(3)SQL注入模拟及解决

(4)perparedStatement使用

7.关于测试类无法使用Scanner的问题解决

二、数据库连接池

1.概述

2.数据库连接池的实现

(1)标准接口:DataSource

(1)常见的数据库连接池

3.Druid数据库连接池的使用

三、综合练习

1.创建表:

2.添加数据:表中数据增

3.表中数据的删、改、查

(1)查(需要啥写啥)+存

(2)改

(3)删除


一、JDBC

1.概述

  • 全称 Java DataBase Connectivity

  • 就是使用Java语言操作关系型数据库的一套API

2.本质

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

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

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

3.好处

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发

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

4.使用步骤

  • 导入对应的驱动jar包

  • 注册驱动,(mysql驱动包在v5及之后的版本,该步骤可省略)

  • 获取连接

  • 定义SQL语句

  • 获取执行SQL对象

  • 执行SQL

  • 返回结果

  • 释放资源

5.JDBC_API

(1)DriverManager(驱动管理类)

主要作用:

  • 注册驱动

  • 获取数据库连接

(2)Connection(数据库连接对象)

主要作用:

  • 获取执行SQL的对象

  • 管理事务

    • JDBC事务管理:Connection接口中定义了3个对应的方法

    • 开启事务: setAutoCommit(boolean autoCommit): true为自动提交事务; false为手动提交事务,即为开启事务

    • 提交事务commit()

    • 回滚事务: rollback()

主要方法:

  • 执行SQL对象(普通)

方法名
Statement createStatement(sql);
  • 执行SQL对象(预编译SQL):防止SQL注入

方法名
PreparedStatement prepareStatement(sql);
  • 执行存储过程的对象

方法名
CallableStatement prepareCall (sql)
(3)Statement

主要作用

  • 执行SQL语句

方法名说明
int executeUpdate(sql);执行DML、DDL语句 返回值为DML语句影响的行数 DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql);执行DQL语句 返回值为ResultSet结果集对象

(4)ResultSet(结果集对象)

主要作用:

  • 获取查询结果

主要方法

方法名说明
boolean next()将光标从当前位置向前移动一行 判断当前行是否为有效行(有数据)
XXX【数据类型】 getXxx(参数)获取数据 参数: int:列的编号,从1开始 String:列的名称 更多参数看jdk帮助文档

使用:

while(rs.next()){
    //获取数据
    rs.getXxx(参数);
}

(5)PreparedStatement

主要作用:

  • 预编译SQL并执行

  • 防止SQL注入

SQL注入:

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

好处:

  • 预编译SQL,性能更高

  • 防止SQL注入:将敏感字符进行转义

注意:

  • 默认只是防止SQL注入,并没有预编译SQL提高性能

  • PreparedStatement的预编译功能默认是关闭的,需要在url后架上useServerPrepStmts=true,才会开启

6.使用

(1)快速上手
import java.sql.*;
​
public class Demo01 {
    public static void main(String[] args) throws Exception {
        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        String username = "root";
        String password = "root";
        //1.注册驱动,mysql5版本及之后的版本该步骤可以省略
        registrationDriver();
        //2.获取数据库连接
        Connection connection = getConnection(url, username, password);
        //3.定义SQL语句
        String sql = "sqls";
        //4.获取执行SQL的对象
        Statement statement = connection.prepareStatement(sql);
        /*开启事务*/
        connection.setAutoCommit(false);
​
        try {
            //5.执行sql,根据方法会返回不同类型的值,详细可查看JDK帮助文档了解
            boolean execute = statement.execute(sql);
            //验证SQL语句是否执行成功
            System.out.println(execute);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            /*出现异常就回滚事务*/
            connection.rollback();
        }
​
        /*提交事务*/
        connection.commit();
​
        //6.释放资源
        statement.close();
        connection.close();
​
    }
​
    /**
     * 获取数据库连接
     * @param url:数据库连接,
     *           格式:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
     *           如果连接的是本机服务器,且端口号为默认,可简写为:jdbc:mysql///数据库名称?参数键值对
     *           由于没有禁用安全连接方式,会输出警告提示,将参数配置设置为 useSSL = false 即可
     * @param username:数据库用户名
     * @param password:数据库密码
     * @return 连接对象
     * @throws SQLException: SQLException异常
     */
    private static Connection getConnection(String url, String username, String password) throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }
​
    private static void registrationDriver() throws ClassNotFoundException {
        Class.forName("com.mysql.jdbc.Driver");
    }
}

(2)ResultSet使用

查询user表中数据,并根据其数据创建User对象,再将所有的User对象存储到arraysList集合中

实体类User:

public class User {
    private Long id;
    private String userName;
    private String password;
    private String gmtCreate;
    private String gmtModified;
​
    public User() {
    }
​
    public User(Long id, String userName, String password, String gmtCreate, String gmtModified) {
        this.id = id;
        this.userName = userName;
        this.password = password;
        this.gmtCreate = gmtCreate;
        this.gmtModified = gmtModified;
    }
​
    public Long getId() {
        return id;
    }
​
    public void setId(Long id) {
        this.id = id;
    }
​
    public String getUserName() {
        return userName;
    }
​
    public void setUserName(String userName) {
        this.userName = userName;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    public String getGmtCreate() {
        return gmtCreate;
    }
​
    public void setGmtCreate(String gmtCreate) {
        this.gmtCreate = gmtCreate;
    }
​
    public String getGmtModified() {
        return gmtModified;
    }
​
    public void setGmtModified(String gmtModified) {
        this.gmtModified = gmtModified;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                ", gmtCreate='" + gmtCreate + '\'' +
                ", gmtModified='" + gmtModified + '\'' +
                '}';
    }
}

测试

public class TestDemo {
    String url = "jdbc:mysql:///test?useSSL=false";
    String userName = "root";
    String password = "root";
    @Test
    public void Demo01 () throws Exception {
        Connection connection = DriverManager.getConnection(url, userName, password);
​
        String sql = "select * from users";
​
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
​
        ArrayList<User> arrayList = new ArrayList<>();
        while (resultSet.next()){
​
            User user = new User(resultSet.getLong("id"),
                                 resultSet.getString("user_name"),
                                 resultSet.getString("password"),
                                 resultSet.getString("gmt_create"),
                                 resultSet.getString("gmt_modified"));
            arrayList.add(user);
        }
        
        resultSet.close();
        statement.close();
        connection.close();
​
        arrayList.forEach(user -> System.out.println(user));
    }
}

(3)SQL注入模拟及解决

模拟登录:sql注入

@Test
    public void sout() throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = scanner.nextLine();
        System.out.println("请输入密码");
        String password = "' or 'a' = 'a";
​
        Connection connection = DriverManager.getConnection(TestDemo.this.url,
                TestDemo.this.userName,
                TestDemo.this.password);
        Statement statement = connection.createStatement();
​
        String sql = "select * from users where user_name = '"+username+"' and password = '"+password+"'";
​
        ResultSet resultSet = statement.executeQuery(sql);
​
        if (resultSet.next()){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
​
        resultSet.close();
        statement.close();
        connection.close();
    }
}

SQL注入本质:由于用户输入导致SQL语句发生变化,如where username = ? and ... +(or 1=1)【后面追加一个恒成立等式,就会导致where条件恒成立】

解决方式1:更多的逻辑判断

@Test
public void demo02() throws Exception {
    Scanner scanner = new Scanner(System.in);
    System.out.println("请输入用户名");
    String username = scanner.nextLine();
    System.out.println("请输入密码");
    String password = scanner.nextLine();
​
    Connection connection = DriverManager.getConnection(TestDemo.this.url,
                                                        TestDemo.this.userName,
                                                        TestDemo.this.password);
    Statement statement = connection.createStatement();
​
    String sql = "select * from users where user_name = '"+username+"' and password = '"+password+"'";
​
    ResultSet resultSet = statement.executeQuery(sql);
​
    while (true){
        boolean next = resultSet.next();
        if (next){
            if (username.equals(resultSet.getString("user_name"))){
                if (password.equals(resultSet.getString("password"))){
                    System.out.println("登录成功");
                }else {
                    System.out.println("密码错误");
                }
                break;
            }
        }else {
            System.out.println("没有此用户");
            break;
        }
​
    }
​
    resultSet.close();
    statement.close();
    connection.close();
}

解决方式2:预编译SQL

(4)perparedStatement使用
  • 获取PerparedStatement对象

    • 使用Connection的prepareStatement(sql)

    • SQL语句中的参数值,使用?占位符替代

  • 设置参数

    • setXxx【数据类型】(int ?的位置编号,参数值)

    • ?位置从1开始

  • 执行SQL

    • 主要方法

    • 方法名返回值类型说明
      execute()boolean可执行所有sql语句,返回值为是否执行成功
      executeUpdate()int执行数据操纵语言DML或者没有返回值类型的SQL,如DDL
      executeQuery()ResultSet执行DQL,返回ResultSet对象

@Test
    public void sout() throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = scanner.nextLine();
        System.out.println("请输入密码");
        String password = scanner.nextLine();
​
        Connection connection = DriverManager.getConnection(TestDemo.this.url,
                TestDemo.this.userName,
                TestDemo.this.password);
​
​
        String sql = "select * from users where user_name=? and password=?";
​
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置?的值
        preparedStatement.setString(1,username);
        preparedStatement.setString(2,password);
​
        ResultSet resultSet = preparedStatement.executeQuery();
​
        if (resultSet.next()){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
​
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

7.关于测试类无法使用Scanner的问题解决

  • 点击Help

  • 选择Edit Custom VM Options...

-Deditable.java.test.console=true
  • 之后重启idea即可

二、数据库连接池

1.概述

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

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

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

好处:

  • 资源重用

  • 提升系统响应速度

  • 避免数据库连接遗漏

2.数据库连接池的实现

(1)标准接口:DataSource

官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口。

功能:

  • 获取连接:getConnection()

(1)常见的数据库连接池
  • DBCP

  • C3P0

  • Druid(德鲁伊)

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

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

3.Druid数据库连接池的使用

  • 导入jar包:druid

  • 定义配置文件

  • 加载配置文件

  • 获取数据库连接池对象

  • 获取连接

配置文件:

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

java代码:

@Test
public void connectionPool() throws Exception {
    //加载配置文件
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\druid.properties"));
​
    //创建连接池对象
    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    //获取数据库连接
    final Connection connection = dataSource.getConnection();
​
    System.out.println(connection);
​
}

三、综合练习

主要目标:

  • 建表:

  • 添加数据:

  • 表中数据的增、删、改、查

  • 表中数据的存储

  • 使用数据库连接池

1.创建表:

这玩意后期不会纯手敲的,除非业务需要

-- auto-generated definition
create table product
(
    id           bigint auto_increment comment '商品ID'
        primary key,
    name         varchar(20)                        not null comment '商品名称',
    price        decimal(10, 2)                     not null comment '商品价格',
    category     int      default 1                 not null comment '商品分类',
    gmt_modified datetime default CURRENT_TIMESTAMP not null comment '最后修改日期',
    gmt_create   datetime default CURRENT_TIMESTAMP not null comment '创建日期',
    constraint product_name_uindex
        unique (name)
)
    comment '商品表';

2.添加数据:表中数据增

id设置主键和自增约束可不写

public class Practice {
    public static void main(String[] args) throws Exception {
​
        //加载配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("JDBC\\src\\practice\\druidDemo.properties"));
​
        //获取连接池连接对象
        final Connection connection = DruidDataSourceFactory.createDataSource(properties).getConnection();
​
        String sql = "insert into product (name,price,category)" +
                     "values(?,?,?)";
        Random random = new Random();
​
​
        final PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (int i = 1; i <= 40; i++) {
            int integerPart = random.nextInt(10001);
            int decimalPart = random.nextInt(100);
            preparedStatement.setString(1,"商品"+i);
            if (decimalPart<10){
                preparedStatement.setString(2,integerPart+".0"+decimalPart);
            }else{
                preparedStatement.setString(2,integerPart+"."+decimalPart);
            }
            preparedStatement.setInt(3,1);
            try {
                preparedStatement.execute();
                System.out.println("第"+i+"条数据添加成功");
            } catch (SQLException e) {
                System.out.println("第"+i+"条数据添加失败");
                e.printStackTrace();
            }
​
        }
​
        preparedStatement.close();
        connection.close();
​
    }
}

3.表中数据的删、改、查

实体类:后面会有优化,也不会手敲的~

public class Product {
    private Long id;
    private String name;
    private BigDecimal bigDecimal;
    private Integer category;
    private Timestamp gmtCreate;
    private Timestamp gmtModified;
​
    public Product() {
    }
​
    public Product(Long id, String name, BigDecimal bigDecimal, Integer category, Timestamp gmtCreate, Timestamp gmtModified) {
        this.id = id;
        this.name = name;
        this.bigDecimal = bigDecimal;
        this.category = category;
        this.gmtCreate = gmtCreate;
        this.gmtModified = gmtModified;
    }
​
    public Long getId() {
        return id;
    }
​
    public void setId(Long id) {
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public BigDecimal getBigDecimal() {
        return bigDecimal;
    }
​
    public void setBigDecimal(BigDecimal bigDecimal) {
        this.bigDecimal = bigDecimal;
    }
​
    public Integer getCategory() {
        return category;
    }
​
    public void setCategory(Integer category) {
        this.category = category;
    }
​
    public Timestamp getGmtCreate() {
        return gmtCreate;
    }
​
    public void setGmtCreate(Timestamp gmtCreate) {
        this.gmtCreate = gmtCreate;
    }
​
    public Timestamp getGmtModified() {
        return gmtModified;
    }
​
    public void setGmtModified(Timestamp gmtModified) {
        this.gmtModified = gmtModified;
    }
​
    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", bigDecimal=" + bigDecimal +
                ", category=" + category +
                ", gmtCreate=" + gmtCreate +
                ", gmtModified=" + gmtModified +
                '}';
    }
}
(1)查(需要啥写啥)+存
        //查询所有
        String sql = "select * from product";
        final PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        ArrayList<Product> productArrayList = new ArrayList<>();
        while (resultSet.next()){
            Product product = new Product(resultSet.getLong(1),
                                          resultSet.getString(2),
                                          resultSet.getBigDecimal(3),
                    resultSet.getInt(4),
                    resultSet.getTimestamp(5),
                    resultSet.getTimestamp(6));
            productArrayList.add(product);
        }
​
        productArrayList.forEach(p -> System.out.println(p));
​
        resultSet.close();
        preparedStatement.close();
        connection.close();
        //根据条件查
        String sql = "select * from product where id = ?";
        final PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setLong(1,10126);
        ResultSet resultSet = preparedStatement.executeQuery();
        ArrayList<Product> productArrayList = new ArrayList<>();
        while (resultSet.next()){
            Product product = new Product(resultSet.getLong(1),
                                          resultSet.getString(2),
                                          resultSet.getBigDecimal(3),
                                          resultSet.getInt(4),
                                          resultSet.getTimestamp(5),
                                          resultSet.getTimestamp(6));
            productArrayList.add(product);
        }
​
        productArrayList.forEach(p -> System.out.println(p));
​
        resultSet.close();
        preparedStatement.close();
        connection.close();
(2)改
public class Practice {
    public static void main(String[] args) throws Exception {
​
        //加载配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\practice\\druidDemo.properties"));
​
        //获取连接池连接对象
        final Connection connection = DruidDataSourceFactory.createDataSource(properties).getConnection();
        //输入sql语句
        String sql = sqls();
​
​
​
​
        final PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //设置参数
        parameterSetting(preparedStatement);
​
       //执行sql
        //execute(),可执行所有SQL语句
        //executeUpdate(),执行DML(返回受影响的行数)或者无返回值的SQL语句,如DDL
        //executeQuery(),DQL,返回ResultSet对象
        preparedStatement.executeUpdate();
​
        //查询专用
        //query(preparedStatement);
​
        preparedStatement.close();
        connection.close();
​
    }
​
    private static void parameterSetting(PreparedStatement preparedStatement) throws SQLException {
        preparedStatement.setInt(1,3);
        preparedStatement.setLong(2,10126);
    }
​
    private static void query(PreparedStatement preparedStatement) throws SQLException {
​
        ResultSet resultSet = preparedStatement.executeQuery();
​
        ArrayList<Product> productArrayList = new ArrayList<>();
        while (resultSet.next()){
            Product product = new Product(resultSet.getLong(1),
                    resultSet.getString(2),
                    resultSet.getBigDecimal(3),
                    resultSet.getInt(4),
                    resultSet.getTimestamp(5),
                    resultSet.getTimestamp(6));
            productArrayList.add(product);
        }
​
        productArrayList.forEach(p -> System.out.println(p));
​
        resultSet.close();
    }
​
    private static String sqls() {
        //查询所有
//        String sql = "select * from product";
        //根据条件查
//        String sql = "select * from product where id = ?";
        //根据条件改
        return "update product set category = ? where id = ?";
    }
}
(3)删除

改SQL,preparedStatement.set一下就行了

String sql = "delete from product where id = ?";

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024-02-01 Unity Shader 开发入门4 —— ShaderLab 语法

文章目录 1 材质和 Shader1.1 Unity Shader 和 Shader 的区别1.2 Unity 中的材质和 Shader1.3 创建材质1.4 创建 Shader 2 ShaderLab 的基本结构2.1 什么是 ShaderLab2.2 ShaderLab 的基本结构 3 Shader 名称4 Shader 属性4.1 Shader 属性的作用4.2 Shader 属性的基本语法4.3 数…

C++初阶:适合新手的手撕string类(模拟实现string类)

上次讲了常用的接口&#xff1a;C初阶&#xff1a;初识STL、String类接口详细讲解&#xff08;万字解析&#xff09; 今天就来进行模拟实现啦 文章目录 1.基本结构与文件规划2.构造函数&#xff08;constructor)2.1构造函数2.1.1无参有参分开2.1.2利用缺省参数合起来 2.2拷贝构…

基于YOLOv8算法的照片角度分类项目实践

目录 一、任务概述二、YOLOv8算法简介2.1 算法改进2.2 算法特点2.3 网络结构2.4 性能比较 三、工程实践3.1 安装算法框架库ultralytics3.2 库存照片预处理3.2.1 提取所有图片3.2.2 去除冗余的相同照片3.2.3 去除无车辆照片3.2.4 随机提取指定数量的图片 3.3 照片朝向分类3.3.1 …

Vue3中插槽选择器和全局选择器

Vue3中插槽选择器和全局选择器 插槽选择器全局选择器1. 再增加style2. 使用:global 插槽选择器 使用场景: 要在定义插槽时定义样式 定义插槽 <template><div>插槽<slot></slot></div> </template><script setup langts></scri…

Linux——权限管理

1、ACL权限 在普通权限中&#xff0c;用户对文件只有三种身份&#xff0c;就是属主、属组和其他人&#xff1b;每种用户身份拥有读&#xff08;read&#xff09;、写&#xff08;write&#xff09;和执行&#xff08;execute&#xff09;三种权限。但是在实际工作中&#xff0…

两个重要极限【高数笔记】

【第一个&#xff1a;lim &#xff08;sinx / x&#xff09; 1, x -- > 0】 1.本质&#xff1a; lim &#xff08;sin‘&#xff1f;’ / ‘&#xff1f;’&#xff09; 1, ‘&#xff1f;’ -- > 0&#xff1b;保证‘&#xff1f;’ -- > 0,与趋向无关 2.例题&#x…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItem组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之MenuItem组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItem组件 TextClock组件通过文本将当前系统时间显示在设备上。支持不同时…

单臂路由实验(华为)

思科设备参考&#xff1a; 单臂路由实验&#xff08;思科&#xff09; 一&#xff0c;实验目的 在路由器的一个接口上通过配置子接口的方式&#xff0c;实现相互隔离的不同vlan之间互通。 ​ 二&#xff0c;设备配置 Switch1 <Huawei>sys [Huawei]vlan batch 10 20…

定时器 Timer(超详细模拟实现)

目录 一、定时器 1.定时器概述 2.Java标准库提供的定时器类 3.定时器代码样例 二、实现 1.实现思路 2.代码实现 2.1纯享版 2.2注释版 3.代码解析(超详细) 3.1描述类MyTimerTask ①构造&#xff1a;MyTimerTask&#xff08;Runnable runnable, long delay&#xff…

[Angular 基础] - Angular 渲染过程 组件的创建

[Angular 基础] - Angular 渲染过程 & 组件的创建 之前的笔记为了推进度写的太笼统了&#xff08;只有功能没有其他&#xff09;&#xff0c;当时学的时候知道是什么东西&#xff0c;但是学完后重新复习发现有些内容就记不清了&#xff0c;所以重新用自己的语言总结一下 …

Linux 多线程 | 线程的互斥

在前面的文章中我们讲述了多线程的一些基本的概念以及相关的操作&#xff0c;那么在本章中我们就将继续讲述与多线程相关的同步与互斥之间的问题。 首先我们使用一个例子引出我们的问题&#xff0c;又一个全局的变量g_val 100&#xff0c;这个变量是被所有的执行流所共享的&a…

MySQL进阶45讲【10】MySQL为什么有时候会选错索引?

1 前言 前面我们介绍过索引&#xff0c;在MySQL中一张表其实是可以支持多个索引的。但是&#xff0c;写SQL语句的时候&#xff0c;并没有主动指定使用哪个索引。也就是说&#xff0c;使用哪个索引是由MySQL来确定的。 大家有没有碰到过这种情况&#xff0c;一条本来可以执行得…

VSCode snippets 自定义Vue3代码片段(持续更新)

在编写Vue代码时发现VSCode中的各类snippets插件无法提供一些常用的代码片段,为避免重复造轮子,提高编码效率,特意自己定义了一些代码片段。为方便初学者,提供了自定义代码片断的方法。 一、 自定义代码片断的方法 1.打开命令面板(Ctrl+Shift+P) 2. 输入 user Snippets…

Hadoop3.x基础(3)- Yarn

来源&#xff1a;B站尚硅谷 目录 Yarn资源调度器Yarn基础架构Yarn工作机制作业提交全过程Yarn调度器和调度算法先进先出调度器&#xff08;FIFO&#xff09;容量调度器&#xff08;Capacity Scheduler&#xff09;公平调度器&#xff08;Fair Scheduler&#xff09; Yarn常用命…

C语言-2

自定义类型 基本认识 /*引入&#xff1a;学生&#xff1a;姓名&#xff0c;学号&#xff0c;年龄&#xff0c;成绩请为学生们专门定制一个类型&#xff08;创造一个类型&#xff09;结构体格式&#xff1a;struct 标识符 // 标识符即自定义类型的名称{成员; // 自己设置…

【Unity知识点详解】自定义程序集

今天来介绍一下Unity中的自定义程序集。在项目开发中我们经常接触到第三方插件的程序集&#xff0c;如DOTween、Newtonsoft.Json等。 使用自定义程序集有这么几个好处&#xff1a; 方便代码的的复用。当某一功能模块需要在多个项目中重复使用时&#xff0c;可以将代码编译成程…

新书速览|Kubernetes从入门到DevOps企业应用实战

从0到1&#xff0c;从零开始全面精通Kubernetes&#xff0c;助力企业DevOps应用实践 本书内容 《Kubernetes从入门到DevOps企业应用实战》以实战为主&#xff0c;内容涵盖容器技术、Kubernetes核心资源以及基于Kubernetes的企业级实践。从容器基础知识开始&#xff0c;由浅入深…

C#中使用OpenCvSharp4绘制直线、矩形、圆、文本

C#中使用OpenCvSharp4绘制直线、矩形、圆、文本 继之前的Python中使用Opencv-python库绘制直线、矩形、圆、文本和VC中使用OpenCV绘制直线、矩形、圆和文字&#xff0c;将之前的Python和C示例代码翻译成C#语言&#xff0c;很简单&#xff0c;还是借用OpenCvSharp4库中的Line、…

基于腾讯云服务器搭建幻兽帕鲁服务器保姆级教程

随着网络游戏的普及&#xff0c;越来越多的玩家希望能够拥有自己的游戏服务器&#xff0c;以便能够自由地玩耍。而腾讯云服务器作为一个优秀的云计算平台&#xff0c;为玩家们提供了一个便捷、稳定、安全的游戏服务器解决方案。本文将为大家介绍如何基于腾讯云服务器搭建幻兽帕…

Fink CDC数据同步(三)Flink集成Hive

1 目的 持久化元数据 Flink利用Hive的MetaStore作为持久化的Catalog&#xff0c;我们可通过HiveCatalog将不同会话中的 Flink元数据存储到Hive Metastore 中。 利用 Flink 来读写 Hive 的表 Flink打通了与Hive的集成&#xff0c;如同使用SparkSQL或者Impala操作Hive中的数据…