JDBC进阶

news2024/11/19 17:44:26

目录

JDBC进阶

实体类和ORM

主键回显

批量操作

连接池

介绍

常见的连接池

Druid连接池

Hikari连接池

连接池与软编码

其他配置

Druid配置

Hikari配置


JDBC进阶

实体类和ORM

在使用JDBC操作数据库时会发现数据都是零散的,明明在数据库中是一行完整的数据,到了Java中变成了一个一个的变量,不利于维护和管理。但是Java是面向对象的,一个表对应的是一个类,一行数据就对应的是Java中的一个对象,一个列对应的是对象的属性,所以需要把数据存储在一个载体里,这个载体就是实体类

ORM(Object Relational Mapping)思想:对象到关系数据库的映射,作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来,以面向对象的角度操作数据库中的数据,即一张表对应一个类,一行数据对应一个对象,一个列对应一个属性

当下JDBC中这种过程称其为手动ORM。后续也会学习ORM框架,比如MyBatis、JPA等。

使用ORM思想优化基础部分六大基本步骤:

  1. 创建对象,一个表就是一个类,表名中表示抽象事物的即为类名,例如t_employee对应类名即为Employee
  2. 将原有「接受一个一个变量逐个打印」的方式更改为「值对应对象的成员属性」
一般实体类会放在一个名为 pojo的包内部

表对应类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer empId;
    private String empName;
    private Double empSalary;
    private Integer empAge;
}

优化六大基本步骤:

public class TestORM {
    @Test
    public void test() throws Exception{
        // 创建数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///databaseTest", "root", "123456");

        // 预编译SQL
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM t_emp WHERE emp_age = 26");

        // 获取结果
        ResultSet resultSet = preparedStatement.executeQuery();

        // 创建对象引用
        Employee employee = null;

        // 遍历结果将数据存储到对象中
        if(resultSet.next()) {
            // 创建对象
            employee = new Employee();
            // 获取值
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            // 将获取到的值存储到对象中
            employee.setEmpId(empId);
            employee.setEmpName(empName);
            employee.setEmpSalary(empSalary);
            employee.setEmpAge(empAge);

            // 上面的也可以直接用构造方法
            // employee = new Employee(resultSet.getInt("emp_id"),
            //         resultSet.getString("emp_name"),
            //         resultSet.getDouble("emp_salary"),
            //         resultSet.getInt("emp_id"));

            System.out.println(employee);

        }
        
        // 关闭资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

如果有多行数据,则可以考虑使用集合,例如ArrayList集合:

public class TestORM01 {
    @Test
    public void test() throws Exception{
        // 创建数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///databaseTest", "root", "123456");

        // 预编译SQL
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM t_emp");

        // 获取结果
        ResultSet resultSet = preparedStatement.executeQuery();

        // 创建对象引用
        Employee employee = null;
        ArrayList<Employee> employees = new ArrayList<>();
        // 遍历结果将数据存储到对象中
        while (resultSet.next()) {
            // 上面的也可以直接用构造方法
            employee = new Employee(resultSet.getInt("emp_id"),
                    resultSet.getString("emp_name"),
                    resultSet.getDouble("emp_salary"),
                    resultSet.getInt("emp_id"));

            employees.add(employee);
        }

        // 显示结果
        employees.stream().forEach(System.out::println);
        // 也可以不用Stream流,因为集合中已经有forEach方法,所以等价于下面的代码
        // employees.forEach(System.out::println);

        // 关闭资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

主键回显

在数据中,执行新增操作时,主键列为自动增长,可以在表中直观的看到,但是在Java程序中执行完新增后,只能得到受影响行数,无法得知当前新增数据的主键值。

在Java程序中获取数据库中插入新数据后的主键值,并赋值给Java对象的操作称为主键回显

需要实现主键回显,就需要在创建PreparedStatement对象时传递一个参数Statement.RETURN_GENERATED_KEYS,该参数表示返回生成的主键,而在插入成功后就可以通过对应的PreparedStatement对象通过getGeneratedKeys()方法获取到一个结果集,但是这个结果集是一个单行单列的,并且因为不知道其表头名,所以需要通过列标的方式获取

例如下面的代码:

public class ReflectPrimKey {
    @Test
    public void test() throws Exception{
        Connection connection = DriverManager.getConnection("jdbc:mysql:///databaseTest", "root", "123456");

        PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp (emp_id, emp_name, emp_salary, emp_age) values (NULL, '李四', 2000, 20)", Statement.RETURN_GENERATED_KEYS);
        int i = preparedStatement.executeUpdate();
        if(i > 0) {
            System.out.println("插入成功");
            Employee employee = null;
            // 主键回显填充到对象
            ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
            if (generatedKeys.next()) {
                int pk = generatedKeys.getInt(1);
                PreparedStatement preparedStatement1 = connection.prepareStatement("SELECT * FROM t_emp where emp_id = ?");
                preparedStatement1.setInt(1, pk);
                ResultSet resultSet = preparedStatement1.executeQuery();
                while (resultSet.next()) {
                    employee = new Employee();
                    employee.setEmpId(pk);
                    employee.setEmpName(resultSet.getString("emp_name"));
                    employee.setEmpAge(resultSet.getInt("emp_age"));
                    employee.setEmpSalary(resultSet.getDouble("emp_salary"));
                }
                resultSet.close();
            }
            System.out.println(employee);
            generatedKeys.close();
        } else {
            System.out.println("插入失败");
        }

        preparedStatement.close();
        connection.close();
    }
}

批量操作

前面插入多条数据时,需要一条一条发送给数据库执行,效率低下,所以需要通过批量操作提升多次操作效率

批量操作步骤:

  1. 在获取数据库连接的URL参数中的数据库后方添加参数rewriteBatchedStatements=true
  2. 添加时使用PreparedStatement对象调用addBatch()方法将新增的数据插入到缓存中
  3. 插入完毕后,使用PreparedStatement对象调用executeBatch()方法将缓冲区的数据直接加载到数据库

例如,使用前面的方式进行多条数据插入:

@Test
public void test() throws Exception{
    Connection connection = DriverManager.getConnection("jdbc:mysql:///databaseTest", "root", "123456");
    PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp (emp_name, emp_salary, emp_age) values (?, ?, ?)");

    for (int i = 0; i < 10000; i++) {
        preparedStatement.setString(1, "marry" + i);
        preparedStatement.setDouble(2, 100+i);
        preparedStatement.setInt(3, 10);
        preparedStatement.executeUpdate();
    }

    preparedStatement.close();
    connection.close();
}

查看运行时长:

使用批量添加多条数据:

@Test
public void test1() throws Exception {
    Connection connection = DriverManager.getConnection("jdbc:mysql:///databaseTest", "root", "123456");
    PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp (emp_name, emp_salary, emp_age) values (?, ?, ?)");

    for (int i = 0; i < 10000; i++) {
        preparedStatement.setString(1, "marry" + i);
        preparedStatement.setDouble(2, 100 + i);
        preparedStatement.setInt(3, 10);
        preparedStatement.addBatch();
    }
    preparedStatement.executeBatch();

    preparedStatement.close();
    connection.close();
}

查看运行时长:

连接池

介绍

前面使用JDBC连接数据库存在下面的两个问题:

  1. 每次操作数据库都要获取新连接,使用完毕后就close释放,频繁的创建和销毁造成资源浪费
  2. 连接的数量无法把控,对服务器来说压力巨大

为了解决上面的两个问题就需要用到连接池:

连接池就是数据库连接对象的缓冲区,通过配置,由连接池负责创建连接、管理连接、释放连接等操作

预先创建数据库连接放入连接池,用户在请求时,通过池直接获取连接,使用完毕后,将连接放回池中,避免了频繁的创建和销毁,同时解决了创建的效率。当池中无连接可用,且未达到上限时,连接池会新建连接。如果池中连接达到上限,用户请求会等待,可以设置超时时间。

常见的连接池

JDBC 的数据库连接池使用javax.sql.DataSourc接口进行规范,所有的第三方连接池都实现此接口,自行添加具体实现。也就是说,所有连接池获取连接的和回收连接方法都一样,不同的只有性能和扩展功能,下面是五种常见的连接池,但是最主要的还是第四种和第五种:

  1. DBCP 是Apache提供的数据库连接池,速度相对C3P0较快,但自身存在一些BUG
  2. C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以
  3. Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能, 稳定性较c3p0差一点
  4. Druid(名:德鲁伊): 是阿里提供的数据库连接池,是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,性能、扩展性、易用性都更好,功能丰富
  5. Hikari(ひかり[shi ga li]): 取自日语,是光的意思,是SpringBoot2.x之后内置的一款连接池,基于 BoneCP (已经放弃维护,推荐该连接池)做了不少的改进和优化,口号是快速、简单、可靠

主流连接池的功能对比:

mock性能数据(单位:ms):

MySQL性能数据 (单位:ms):

Druid连接池

因为是第三方的工具,所以需要引入jar

使用方式步骤:

  1. 创建连接池对象(使用DruidDatasource的无参构造方法创建)
  2. 为连接数据库提供必要数据:
    1. 数据库驱动(使用DruidDatasource对象的方法:setDriverClassName(),参数传递驱动全限定名)
    2. 数据库URL(使用DruidDatasource对象的方法:setUrl(),参数传递数据库URL)
    3. 数据库用户名(使用DruidDatasource对象的方法:setUsername(),参数传递数据库用户名)
    4. 数据库密码(使用DruidDatasource对象的方法:setPassword(),参数传递数据库用户名密码)
  3. 可选设置:
    1. 连接池初始时提供连接的总数量(使用DruidDatasource对象的方法:setInitialSize(),参数传递整数个数值)
    2. 连接池最大可提供连接的数量(使用使用DruidDatasource对象的方法:setMaxActive(),参数传递整数个数值)
注意,如果写了初始值,若初始值大于8,则必须要给最大值,否则会报错
  1. 获取连接池对象(使用DruidDatasource对象的方法:getConnection(),返回DruidPooledConnection对象,但是DruidPooledConnectionConnection的实现类,所以也可以用Connection对象引用来接收)
  2. 释放连接:使用连接对象调用close()方法释放

示例代码:

public class DruidConnectionPool {
    @Test
    public void test() throws Exception{
        // 1. 创建DruidDataSource对象
        DruidDataSource druidDataSource = new DruidDataSource();

        // 2. 设置数据库信息
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql:///databaseTest");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123456");

        // 3. 非必要信息设置
        druidDataSource.setInitialSize(10);
        druidDataSource.setMaxActive(20);

        // 4. 获取连接池连接
        DruidPooledConnection connection = druidDataSource.getConnection();
        System.out.println(connection);

        // 5. 处理CRUD

        // 释放连接池
        connection.close();
    }
}

看到如下内容代表连接池创建完成:

Hikari连接池

因为是第三方的工具,所以需要引入jar

使用步骤与Druid基本一致,只是部分方法的名称不同:

使用方式步骤:

  1. 创建连接池对象(使用HikariDataSource的无参构造方法创建)
  2. 为连接数据库提供必要数据:
    1. 数据库驱动(使用HikariDataSource对象的方法:setDriverClassName(),参数传递驱动全限定名)
    2. 数据库URL(使用HikariDataSource对象的方法:setJdbcUrl(),参数传递数据库URL)
    3. 数据库用户名(使用HikariDataSource对象的方法:setUsername(),参数传递数据库用户名)
    4. 数据库密码(使用HikariDataSource对象的方法:setPassword(),参数传递数据库用户名密码)
  3. 可选设置:
    1. 连接池初始时提供连接的总数量(使用HikariDataSource对象的方法:setMinimumIdle(),参数传递整数个数值)
    2. 连接池最大可提供连接的数量(使用使用HikariDataSource对象的方法:setMaximumPoolSize(),参数传递整数个数值)
注意,如果写了初始值,若初始值大于8,则必须要给最大值,否则会报错
  1. 获取连接池对象(使用HikariDataSource对象的方法:getConnection(),返回Connection对象)
  2. 释放连接:使用连接对象调用close()方法释放
public class HikariConnectionPool {
    @Test
    public void test() throws Exception{
        // 1. 创建HikariDataSource对象
        HikariDataSource hikariDataSource = new HikariDataSource();

        // 2. 设置数据库信息
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        hikariDataSource.setJdbcUrl("jdbc:mysql:///databaseTest");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("123456");

        // 3. 非必要信息设置
        hikariDataSource.setMinimumIdle(10);
        hikariDataSource.setMaximumPoolSize(20);

        // 4. 获取连接池连接
        Connection connection = hikariDataSource.getConnection();
        System.out.println(connection);

        // 5. 处理CRUD

        // 释放连接池
        connection.close();
    }
}

看到如下结果代表连接池创建成功:

当在Java应用程序中看到「SLF4J: No SLF4J providers were found.」这条信息时,这意味着Simple Logging Facade for Java(SLF4J)没有找到任何绑定(binding),即它无法找到具体的日志实现来执行日志记录。SLF4J本身只是一个用于访问底层日志框架的接口或facade,它需要一个具体的实现(如Logback或log4j-over-SLF4J)来实际记录日志消息,但是目前可以不需要进行具体研究

连接池与软编码

前面在创建连接池时都是使用的硬编码,但是在实际开发中,如果将这些配置信息与Java代码耦合,则每一次更新迭代都需要改变源代码,导致维护成本升高,为了解决这个问题,可以将连接池的相关配置信息放到一个xxx.properties的文件,使用Properties集合的load()方法读取配置文件中的信息

配置文件创建基本步骤如下:

  1. 创建resources文件夹并将其标记为根资源文件夹,存放配置文件
  2. 在配置文件中写入连接池的配置信息,一般包括如下内容:
    1. 数据库驱动全限定名
    2. 数据库URL
    3. 数据库用户名
    4. 数据库用户名密码
  3. 可选写内容:
    1. 连接池初始连接总数量
    2. 连接池最大连接数量
建议在设置配置文件每一个key时,名字取setXxx方法后面的Xxx并将首字母小写,例如setDriverClassName,在配置文件中写driverClassName

使用软编码步骤如下:

  1. 创建Properties集合
  2. 通过当前类名.class.ClassLoader().getResourcesAsStream()获取一个InputStream对象
  3. 通过Properties集合中的load()方法读取数据
  4. Properties集合对象通过连接池的相关方法传入从而创建指定连接池:
    1. 对于Druid:使用DruidDataSourceFactory.createDataSource()方法,参数传递Properties集合对象
    2. 对于Hikari:使用构造方法:HikariConfig(),参数传递Properties集合对象,创建一个HikariConfig对象,通过HikariConfig对象调用HikariDataSource()的构造方法,参数传递HikariConfig对象,创建HikariDataSource对象

对于Druid来说:

配置文件:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///databaseTest
username=root
password=123456
initialSize=10
maxActive=20

示例代码:

@Test
public void softCode() throws Exception{
    // 创建Properties集合
    Properties properties = new Properties();
    // 获取配置文件
    InputStream resourceAsStream = DruidConnectionPool.class.getClassLoader().getResourceAsStream("druid.properties");
    properties.load(resourceAsStream);
    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

    // 获取连接对象
    Connection connection = dataSource.getConnection();
    System.out.println(connection);

    // 释放连接
    connection.close();
}

对于Hikari来说:

配置文件:

driverClassName=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///databaseTest
username=root
password=123456
minimumIdle=10
maximumPoolSize=20

示例代码:

@Test
public void softCode() throws Exception{
    // 创建Properties集合
    Properties properties = new Properties();
    // 获取配置文件
    InputStream resourceAsStream = HikariConnectionPool.class.getClassLoader().getResourceAsStream("hikari.properties");
    properties.load(resourceAsStream);
    HikariConfig hikariConfig = new HikariConfig(properties);
    HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);

    // 获取连接对象
    Connection connection = hikariDataSource.getConnection();
    System.out.println(connection);

    // 释放连接
    connection.close();
}

其他配置

Druid配置

配置

缺省

说明

name

配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this)

jdbcUrl

连接数据库的url,不同数据库不一样。例如:mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto

username

连接数据库的用户名

password

连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:使用ConfigFilter · alibaba/druid Wiki · GitHub

driverClassName

根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)

initialSize

0

初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection

maxActive

8

最大连接池数量

maxIdle

8

已经不再使用,配置了也没效果

minIdle

最小连接池数量

maxWait

获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。

poolPreparedStatements

false

是否缓存preparedStatement,也就是PSCachePSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。

maxOpenPreparedStatements

-1

要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在OraclePSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100

validationQuery

用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuerynulltestOnBorrowtestOnReturntestWhileIdle都不会其作用。

testOnBorrow

true

申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

testOnReturn

false

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能

testWhileIdle

false

建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

timeBetweenEvictionRunsMillis

有两个含义:

  1. Destroy线程会检测连接的间隔时间
  2. testWhileIdle的判断依据,详细看testWhileIdle属性的说明

numTestsPerEvictionRun

不再使用,一个DruidDataSource只支持一个EvictionRun

minEvictableIdleTimeMillis

connectionInitSqls

物理连接初始化的时候执行的sql

exceptionSorter

根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接

filters

属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall

proxyFilters

类型是List,如果同时配置了filtersproxyFilters,是组合关系,并非替换关系

Hikari配置

属性

默认值

说明

isAutoCommit

true

自动提交从池中返回的连接

connectionTimeout

30000

等待来自池的连接的最大毫秒数

maxLifetime

1800000

池中连接最长生命周期如果不等于0且小于30秒则会被重置回30分钟

minimumIdle

10

池中维护的最小空闲连接数 minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize

maximumPoolSize

10

池中最大连接数,包括闲置和使用中的连接

metricRegistry

null

连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置

healthCheckRegistry

null

报告当前健康信息

poolName

HikariPool-1

连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置

idleTimeout

是允许连接在连接池中空闲的最长时间

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

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

相关文章

【四】Spring Cloud OpenFeign原理分析

Spring Cloud OpenFeign原理分析 概述 Spring Cloud 微服务实践也有挺多年了&#xff0c;一直想着总结一下这系列的知识点&#xff0c;最近终于下定决心来出一个Spring Cloud 系列文章了。本文主要围绕fegin组件来进行讲解&#xff0c;文中将会给出基础使用的示例&#xff0c;还…

0x10 用友 畅捷通T+ RecoverPassword.aspx 管理员密码修改漏洞

参考&#xff1a; 用友 畅捷通T RecoverPassword.aspx 管理员密码修改漏洞 | PeiQi文库 (wgpsec.org) 免责声明 欢迎访问我的博客。以下内容仅供教育和信息用途&#xff1a; 合法性&#xff1a;我不支持或鼓励非法活动。请确保遵守法律法规。信息准确性&#xff1a;尽管我尽…

全站最详细的Python环境配置步骤

1、官网下载IDE JetBrains下载 2、IDE下载、安装步骤 这里展示的是如何在Windows上下载、安装Pycharm工具&#xff0c;Linux的步骤类似。 2.1、选择开发者工具 选择开发者工具 2.2、选择Pycharm 选择Pycharm 2.3、选择下载 选择下载 2.4、选择社区版 一般而言&#xff…

【STM32-HAL库】AHT10温湿度传感器使用(STM32F407ZGT6配置i2c)(附带工程下载连接)

一、温湿度传感器&#xff1a; 温湿度传感器是一种能够检测环境中的温度和湿度&#xff0c;并将其转化为电信号输出的装置。它在智能家居、工业自动化、气象监测、农业等领域有着广泛的应用。 原理&#xff1a; 温湿度传感器通常基于不同的物理原理&#xff0c;以下是一些常见…

补:vs调试技巧!

目录 1>>闲话 2>>bug 3>>debug调式 4>>debug和release 5>>监视和内存观察 6>>总结 1>>闲话 数据结构章节在国庆后再给大家更喔&#xff0c;现在先把c基础打好&#xff0c;所以我又重返回去学习c语言&#xff0c;并且&#xff0…

17 vue3之tsx手写vite tsx插件

我们之前呢是使用Template去写我们模板。现在可以扩展另一种风格TSX风格 vue2 的时候就已经支持jsx写法&#xff0c;只不过不是很友好&#xff0c;随着vue3对typescript的支持度&#xff0c;tsx写法越来越被接受&#xff0c;减少我们学习react的成本 Ant Design组件库就是使用…

利用LLMs自动寻找量化投资策略

利用LLMs自动寻找量化投资策略 J.P.Morgan的python教程 Content 本文提出了一个利用大型语言模型&#xff08;LLMs&#xff09;和多代理架构的新框架&#xff0c;用于量化股票投资和投资组合管理。该框架通过整合LLMs生成多样化的alpha因子&#xff0c;并动态评估市场条件&am…

基于 QAnything 的知识库问答系统:技术解析与应用实践

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

Mysql 学习——项目实战

MySQL 学习——项目实战 项目出处 博主&#xff1a;Asmywishi Linux-Ubuntu启动Mysql sudo mysqlData preparation Create Database and Table Create database : create database mysql_example1;Start database : use mysql_example1;Create Student table : # 学生表…

vue页面保持在div的底部(适用于聊天界面等需要显示最新信息的场景)

代码示例&#xff1a; <script setup lang"ts"> import {nextTick, onMounted, ref} from vueconst count [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, …

如何将题目文档做成一个题库刷题小程序?

✨告别题海战术&#xff0c;迎接智慧刷题新时代&#xff01;&#x1f680; &#x1f4da;面对堆积如山的题库文档&#xff0c;是否感到无从下手&#xff1f;别担心&#xff0c;这款本土定制刷题小程序来救场啦&#xff01;&#x1f389; &#x1f31f;自动生成题库&#xff0c…

数据结构-3.9.栈在递归中的应用

一.函数被调用背后的过程&#xff1a;最后被调用的函数最先结束也符合栈的后进先出 1.main函数为主函数即程序入口&#xff0c;运行时主函数先入栈&#xff0c;然后存入主函数里的数据&#xff1b; 2.func1函数加载在栈中时他后面的代码的地址#1(调用返回地址&#xff0c;不是…

Xshell7下载及服务器连接

一、Xshell-7.0.0164p、Xftp 7下载 1.1、文件下载 通过网盘分享的文件&#xff1a;xshell 链接: https://pan.baidu.com/s/1qc0CPv4Hkl19hI9tyvYZkQ 提取码: 5snq –来自百度网盘超级会员v2的分享 1.2、ip连接 下shell和xftp操作一样&#xff1a;找到文件—》新建—》名称随…

链表OJ经典题目及思路总结(一)

目录 前言1.移除元素1.1 链表1.2 数组 2.双指针2.1 找链表的中间结点2.2 找倒数第k个结点 总结 前言 解代码题 先整体&#xff1a;首先数据结构链表的题一定要多画图&#xff0c;捋清问题的解决思路&#xff1b; 后局部&#xff1a;接着考虑每一步具体如何实现&#xff0c;框架…

JavaScript 数学基础:数字与运算符解析——WEB开发系列43

哈哈哈哈可能不是每个人都喜欢数学。有些人从小就享受解决复杂的数学问题&#xff0c;而另一些人则在学校被迫学习乘法表和长除法时对数学产生了厌恶。尽管如此&#xff0c;数学仍是生活中不可或缺的组成部分。无论我们处在哪里&#xff0c;数学的应用在我们生活中随处可见。在…

使用 ModelScope Studio 实现可滚动 ChatBot

前面的文章提到过 Gradio 的 Chatbot 不能自动滚动的问题&#xff0c;最近看到了 ModelScope Studio 扩展的一些组件&#xff0c;其中 Chatbot 就完美解决了自动滚动的问题&#xff0c;同时还增加了很多更细化的功能&#xff0c;例如可以设置用户和 AI 的头像。官方文档&#x…

C++进阶(3): 二叉搜索树

二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有的节点的值都小于等于 根节点的值若它的右子树不为空&#xff0c;则右子树上所有的节点的值都大于等…

时序必读论文15|TimeXer:通过外部变量增强Transformer在时间序列预测中的能力

论文标题&#xff1a;TimeXer: Empowering Transformers for Time Series Forecasting with Exogenous Variables 论文链接&#xff1a;https://arxiv.org/abs/2402.19072 前言 仅仅关注内生变量&#xff0c;通常不足以保证准确的预测&#xff0c;外部序列可以为内生变量提供…

MongoDB 副本集搭建 【docker compose + 本机部署】【建议收藏起来】

什么是副本集 MongoDB副本集&#xff08;Replica Set&#xff09;是一种数据冗余和故障恢复机制&#xff0c;它允许你维护相同数据的一个或多个副本&#xff0c;并提供自动故障转移和数据恢复能力。副本集是一个包含多个MongoDB实例&#xff08;通常称为成员&#xff09;的集合…

Linux学习笔记(一):Linux学习环境的安装及远程连接工具的使用

Linux学习笔记&#xff08;一&#xff09;&#xff1a;Linux学习环境的安装及远程连接工具的使用 本地安装虚拟机 1.安装VMWare(点击图片跳转下载&#xff09; 2.安装CentOS7光盘源(点击图片下载&#xff09; 3.安装 一路点下一步 点击确认 等待不要动,可能有点久,直到这个…