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

Java—JDBC 和数据库连接池

一、JDBC 概述

1.基本介绍

  1. JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。
  2. Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。
  3. JDBC的基本原理图「[重要!]在这里插入图片描述

2. 模拟JDBC

(1)创建接口模拟jdbc接口

package com.hspedu.jdbc.myjdbc;//我们规定的 jdbc 接口(方法)
public interface JdbcInterface {//连接public Object getConnection();//crudpublic void crud();//关闭连接public void close();
}

(2)创建Mysql/Oracle类 模拟 Mysql/Oracle数据库实现jdbc接口

package com.hspedu.jdbc.myjdbc;
//mysql数据库实现jdbc接口[模拟] 【由mysql厂商开发】
public class Mysql_jdbc implements JdbcInterface {@Overridepublic Object getConnection() {System.out.println("得到mysql的连接");return null;}@Overridepublic void crud() {System.out.println("完成mysql的增删改查");}@Overridepublic void close() {System.out.println("关闭mysql的连接");}
}
package com.hspedu.jdbc.myjdbc;public class Oracle_jdbc implements JdbcInterface{@Overridepublic Object getConnection() {System.out.println("得到oracle的连接");return null;}@Overridepublic void crud() {System.out.println("得到oracle的增删改查");}@Overridepublic void close() {System.out.println("关闭oracle的连接");}
}

(3)完成对 mysql 的操作

package com.hspedu.jdbc.myjdbc;public class Test_JDBC {public static void main(String[] args) {//完成对 mysql 的操作JdbcInterface jdbcInterface = new Mysql_jdbc();jdbcInterface.getConnection();//通过接口来调用实现类【动态绑定】jdbcInterface.crud();jdbcInterface.close();//完成对 oracle 的操作System.out.println("=====================================================");jdbcInterface = new Oracle_jdbc();jdbcInterface.getConnection();//通过接口来调用实现类【动态绑定】jdbcInterface.crud();jdbcInterface.close();}
}

结果为:在这里插入图片描述

3.JDBC带来的好处

  1. 如果java直接访问数据库 (太单调)在这里插入图片描述
  2. JDBC带来的好处
    在这里插入图片描述
  3. 说明:JDBC是Java提供一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程即可。同的数据库厂商,供不同实现。

4. JDBC API

(javax.sql是扩展包)
在这里插入图片描述

二、JDBC 快速入门

1. JDBC 程序编写步骤

  • 1.注册驱动 - 加载Driver 类
  • 2.获取连接 - 得到Connection
  • 3.执行增删改查 - 发送SQL 给mysql执行
  • 4.释放资源 - 关闭相关连接

2.获取数据库连接

(1)首先在mysql中新建一个actor表

use db01;
create table actor(-- 演员表
id int primary key auto_increment,
name varchar(32) not null default '',
sex char(1) not null default '女',
borndate datetime,
phone varchar(12));

通过jdbc对 actor表进行 添加、删除和修改
(2)新建文件输入配置信息

user=root
password=hsp
url=jdbc:mysql://localhost:3306/db01?characterEncoding=utf8&useSSL=false
driver=com.mysql.jdbc.Driver

(3)通过jdbc对 actor表进行 添加、删除和修改

package com.hspedu.jdbc;
import org.junit.jupiter.api.Test;
import java.sql.*;
import java.util.Properties;
//前置工作: 在项目下创建一个文件夹比如 libs
// 将 mysql.jar 拷贝到该目录下,点击 add to project ..加入到项目中
public class jdbcConn {public void connect01() throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {//1.通过 Properties 对象获取配置文件的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\Test.mysql.properties"));//2.获取相关的值String user = properties.getProperty("user");String password = properties.getProperty("password");String url = properties.getProperty("url");String driver = properties.getProperty("driver");Connection connection = DriverManager.getConnection(url, user, password);Class.forName(driver);//建议写//3.执行sql操作//1)添加String sql = "insert into actor values(null, '刘德华', '男', '1970-11-11', '110')";//2)修改//String sql = "update actor set name='周星驰' where id = 1";//3)删除//String sql = "delete from actor where id = 1";//statement 用于执行静态 SQL 语句并返回其生成的结果的对象Statement statement = connection.createStatement();int rows = statement.executeUpdate(sql);// 如果是 dml 语句,返回的就是影响行数System.out.println(rows>0?"成功":"失败");//4.关闭连接资源statement.close();connection.close();

中文变成问号的看这里!在url后面加 ?characterEncoding=utf8
提示 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
在url后面再加&useSSL=true

3. ResultSet[结果集]

就当迭代器就好了

(1)基本介绍

1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
2.ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前
3.next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false ,因此可以在while循环中使用循环来遍历结果集

  • 原理
    在这里插入图片描述

(2)实践

//通过 Properties 对象获取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");//1. 注册驱动
Class.forName(driver);//建议写上
//2. 得到连接
Connection connection = DriverManager.getConnection(url, user, password);
//3. 得到 Statement
Statement statement = connection.createStatement();
//4. 组织 SqL
String sql = "select id, name , sex, borndate from actor";
//执行给定的 SQL 语句,该语句返回单个 ResultSet 对象
/*
+----+-----------+-----+---------------------+
| id | name | sex | borndate |
+----+-----------+-----+---------------------+-------+
| 4 | 刘德华 || 1970-12-12 00:00:00 |
| 5 | jack || 1990-11-11 00:00:00 |
+----+-----------+-----+---------------------+-------+
*/ResultSet resultSet = statement.executeQuery(sql);//5. 使用 while 取出数据
while (resultSet.next()) { // 让光标向后移动,如果没有更多行,则返回 falseint id = resultSet.getInt(1); //获取该行的第 1//int id1 = resultSet.getInt("id"); 通过列名来获取值, 推荐String name = resultSet.getString(2);//获取该行的第 2 列String sex = resultSet.getString(3);Date date = resultSet.getDate(4);System.out.println(id + "\t" + name + "\t" + sex + "\t" + date);
}//6. 关闭连接
resultSet.close();
statement.close();
connection.close();
}

4.Statement

(1)基本介绍

在这里插入图片描述

(2)应用实例

  • 先创建表
create table admin(
name varchar(32) not null unique,
pwd varchar(32) not null default "
')character set utf8;
Scanner scanner = new Scanner(System.in);
//让用户输入管理员名和密码
System.out.print("请输入管理员的名字: "); //next(): 当接收到 空格或者 '就是表示结束
String admin_name = scanner.nextLine(); // 老师说明,如果希望看到 SQL 注入,这里需要用 nextLine
System.out.print("请输入管理员的密码: ");
String admin_pwd = scanner.nextLine();
//通过 Properties 对象获取配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
//1. 注册驱动
Class.forName(driver);//建议写上
//2. 得到连接
Connection connection = DriverManager.getConnection(url, user, password);
//3. 得到 Statement
Statement statement = connection.createStatement();
//4. 组织 SqL
String sql = "select name , pwd from admin where name ='" + admin_name + "' and pwd = '" + admin_pwd + "'";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) { //如果查询到一条记录,则说明该管理存在
System.out.println("恭喜, 登录成功");
} else {
System.out.println("对不起,登录失败");
}
//关闭连接
resultSet.close();
statement.close();
connection.close();

5. PreparedStatement(预处理)

(1)基本介绍

在这里插入图片描述

(2)预处理的好处

  1. 不再使用+ 拼接sql语句,减少语法错误
  2. 有效的解决了sql注入问题!!
  3. 大大减少了编译次数,效率较高
//3. 得到 PreparedStatement
//3.1 组织 SqL , Sql 语句的 ? 就相当于占位符
//添加记录
//String sql = "insert into admin values(?, ?)";
//String sql = "update admin set pwd = ? where name = ?";
String sql = "delete from admin where name = ?";
//3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.3 给 ? 赋值
preparedStatement.setString(1, admin_name);
//preparedStatement.setString(2, admin_name);
//4. 执行 dml 语句使用 executeUpdate
int rows = preparedStatement.executeUpdate();
System.out.println(rows > 0 ? "执行成功" : "执行失败");

注意顺序不要颠倒

6. JDBC 的相关 API 小结

在这里插入图片描述
在这里插入图片描述

7. 封装 JDBCUtils 【关闭连接, 得到连接】

1. 说明

在jdbc 操作中,获取连接和 释放资源 是经常使用到可以将其封装JDBC连接的工具类 JDBCUtils

2. 实际使用使用工具类 JDBCUtils

  • 这是一个工具类,完成 mysql 的连接和关闭资源
public class JDBCUtils {
//定义相关的属性(4), 因为只需要一份,因此,我们做出 staticprivate static String user; //用户名private static String password; //密码private static String url; //urlprivate static String driver; //驱动名
//在 static 代码块去初始化
static {
try {Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));
//读取相关的属性值user = properties.getProperty("user");password = properties.getProperty("password");url = properties.getProperty("url");driver = properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中,我们可以这样处理
//1. 将编译异常转成 运行异常
//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便. throw new RuntimeException(e);
}
}
//连接数据库, 返回 Connection
public static Connection getConnection() {
try {return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
//1. 将编译异常转成 运行异常
//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便. throw new RuntimeException(e);
}
}
//关闭相关资源
/*
1. ResultSet 结果集
2. Statement 或者 PreparedStatement
3. Connection
4. 如果需要关闭资源,就传入对象,否则传入 null
*/
public static void close(ResultSet set, Statement statement, Connection connection) {
//判断是否为 null
try {if (set != null) {set.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}
} catch (SQLException e) {
//将编译异常转成运行异常抛出
throw new RuntimeException(e);}}
}

方法中才能抛出异常, 这里是代码块中
快捷键ctrl+alt+t

  • 该类演示如何使用 JDBCUtils 工具类,完成 dml 和 select
public class JDBCUtils_Use {
@Test
public void testSelect() {
//1. 得到连接
Connection connection = null;
//2. 组织一个 sql
String sql = "select * from actor where id = ?";
PreparedStatement preparedStatement = null;
ResultSet set = null;
//3. 创建 PreparedStatement 对象
try {connection = JDBCUtils.getConnection();System.out.println(connection.getClass()); //com.mysql.jdbc.JDBC4ConnectionpreparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, 5);//给?号赋值
//执行, 得到结果集
set = preparedStatement.executeQuery();
//遍历该结果集
while (set.next()) {int id = set.getInt("id");String name = set.getString("name");String sex = set.getString("sex");Date borndate = set.getDate("borndate");String phone = set.getString("phone");System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(set, preparedStatement, connection);
}
}
@Test
public void testDML() {//insert , update, delete
//1. 得到连接
Connection connection = null;
//2. 组织一个 sql
String sql = "update actor set name = ? where id = ?";
// 测试 delete 和 insert ,自己玩. PreparedStatement preparedStatement = null;
//3. 创建 PreparedStatement 对象
try {connection = JDBCUtils.getConnection();preparedStatement = connection.prepareStatement(sql);
//给占位符赋值preparedStatement.setString(1, "周星驰");preparedStatement.setInt(2, 4);
//执行preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null, preparedStatement, connection);}}
}

8. 事务

(1)基本介绍

  1. JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
  2. JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务
  3. 调用Connection的setAutoCommit(false)可以取消自动提交事务在所有的SQL语句都成功执行后,调用Connection的commit():方法提交事务
  4. 在其中某个操作失败或出现异常时,调用Connection的rollback();方法回滚事务

9.批处理

(1) 基本介绍

在这里插入图片描述
更方便,省时间

(2)源码分析

在这里插入图片描述

10. 数据库连接池

作用:解决连接次数多后耗时久的问题

(1)传统获取 Connection 问题分析

  1. 传统的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证IP地址,用户名密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。
  2. 每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终将导致重启数据库。
  3. 传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄漏,MySQL崩溃。
  4. 解决传统开发中的数据库连接问题,可以采用数据库连接池技术(connection pool)

(2) 数据库连接池种类

  1. JDBC 的数据库连接池使用javax.sql.DataSource 来表示,DataSource只是一个接口,该接口通常由第三方提供实现[提供.jar]
  2. C3P0 数据库连接池,速度相对较慢,稳定性不错(hibernate, spring)
  3. DBCP数据库连接池,速度相对c3p0较快,但不稳定有监控连接池状态的功能,稳定性较c3p0差一点
  4. Proxool数据库连接池,BoneCP 数据库连接池,速度快
  5. Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池

(3)C3P0 应用实例

//1. 将 c3p0 提供的 c3p0.config.xml 拷贝到 src 目录下
//2. 该文件指定了连接数据库和连接池的相关参数
@Test
public void testC3P0_02() throws SQLException {ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("hsp_edu");//测试 5000 次连接 mysqllong start = System.currentTimeMillis();System.out.println("开始执行....");for (int i = 0; i < 500000; i++) {Connection connection = comboPooledDataSource.getConnection();//System.out.println("连接 OK~");connection.close();}long end = System.currentTimeMillis();//c3p0 的第二种方式 耗时=413System.out.println("c3p0 的第二种方式(500000) 耗时=" + (end - start));//1917}
}

(4)Druid(德鲁伊)应用实例


public void testDruid() throws Exception {//1. 加入 Druid jar 包//2. 加入 配置文件 druid.properties , 将该文件拷贝项目的 src 目录//3. 创建 Properties 对象, 读取配置文件Properties properties = new Properties();properties.load(new FileInputStream("src\\druid.properties"));//4. 创建一个指定参数的数据库连接池, Druid 连接池DataSource dataSource =DruidDataSourceFactory.createDataSource(properties);long start = System.currentTimeMillis();for (int i = 0; i < 500000; i++) {Connection connection = dataSource.getConnection();System.out.println(connection.getClass());//System.out.println("连接成功!");connection.close();}long end = System.currentTimeMillis();//druid 连接池 操作 5000 耗时=412System.out.println("druid 连接池 操作 500000 耗时=" + (end - start));//539
}

(5)将 JDBCUtils 工具类改成 Druid(德鲁伊)实现

try/catch快捷键:Ctrl + Alt + T
在这里插入图片描述

 private static DataSource ds;//在静态代码块完成 ds 初始化static {Properties properties = new Properties();try {properties.load(new FileInputStream("src\\druid.properties"));ds= DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {throw new RuntimeException(e);}}//编写getConnection方法public static Connection getConnection() throws SQLException {return ds.getConnection();}//关闭连接, 老师再次强调: 在数据库连接池技术中,close 不是真的断掉连接//而是把使用的 Connection 对象放回连接池public static void close(ResultSet resultSet, Statement statement, Connection connection){try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}

11.Apache—DBUtils

(1)解决什么问题

  1. 关闭connection 后,resultSet 结果集无法使用
  2. resultSet 不利于数据的管理

(程序需要使用结果集,但结果集与连接是关联的,连接关闭后就不能使用结果集了)
在这里插入图片描述

这里就是把我们的sql表 当做 类来使用。一个类对象对应一行数据
相当于把数据库的需要的内容抄了一份下来存在集合中,简单的说就是储存起来了

(2)基本介绍

在这里插入图片描述

(3)应用实例

在这里插入图片描述

1.apache-dbutils + druid 完成 查询
@Test
public void testQueryMany() throws SQLException { //返回结果是多行的情况//1. 得到 连接 (druid)Connection connection = JDBCUtilsByDruid.getConnection();//2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project//3. 创建 QueryRunnerQueryRunner queryRunner = new QueryRunner();//4. 就可以执行相关的方法,返回 ArrayList 结果集//String sql = "select * from actor where id >= ?";// 注意: sql 语句也可以查询部分列String sql = "select id, name from actor where id >= ?";
// 解读
//(1) query 方法就是执行 sql 语句,得到 resultset ---封装到 --> ArrayList 集合中
//(2) 返回集合
//(3) connection: 连接
//(4) sql : 执行的 sql 语句
//(5) new BeanListHandler<>(Actor.class): 在将 resultset -> Actor 对象 -> 封装到 ArrayList
// 底层使用反射机制 去获取 Actor 类的属性,然后进行封装
//(6) 1 就是给 sql 语句中的? 赋值,可以有多个值,因为是可变参数 Object... params
//(7) 底层得到的 resultset ,会在 query 关闭, 关闭 PreparedStatment

返回单个记录单个对象
在这里插入图片描述
演示 apache-dbutils + druid 完成查询结果是单行单列-返回的就是 object
在这里插入图片描述

2.apache-dbutils + druid 完成 dml (update, insert ,delete)
@Test
public void testDML() throws SQLException {//1. 得到 连接 (druid)Connection connection = JDBCUtilsByDruid.getConnection();//2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project//3. 创建 QueryRunnerQueryRunner queryRunner = new QueryRunner();//4. 这里组织 sql 完成 update, insert delete//String sql = "update actor set name = ? where id = ?";//String sql = "insert into actor values(null, ?, ?, ?, ?)";String sql = "delete from actor where id = ?";//解读//(1) 执行 dml 操作是 queryRunner.update()//(2) 返回的值是受影响的行数 (affected: 受影响)//int affectedRow = queryRunner.update(connection, sql, "林青霞", "女", "1966-10-10", "116");int affectedRow = queryRunner.update(connection, sql, 1000 );System.out.println(affectedRow > 0 ? "执行成功" : "执行没有影响到表");// 释放资源JDBCUtilsByDruid.close(null, null, connection);}
}

(4)表和 JavaBean 的类型映射关系

在这里插入图片描述

12. BasicDAO 和增删改查通用方法-BasicDao

(1)DBUtils的不足

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)DAO基本介绍

在这里插入图片描述

(3)应用案例

其实就是封装各种功能
在这里插入图片描述

import com.jdbc.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;// 其他DAO的父类
public class BasicDAO<T> {private QueryRunner qr = new QueryRunner();//开发通用的DML方法,针对任意的表public int update(String sql, Object... parameters){Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();int update = qr.update(connection, sql, parameters);return update;} catch (SQLException e) {throw new RuntimeException(e);} finally {JDBCUtilsByDruid.closeConnection(null,connection,null);}}/**** @param sql sql语句,可以有占位符?* @param tClass 传入一个Class类对象,方便反射* @param parameters 传入占位符?的具体数值,可以是多个* @return 根据传入的Class类对象,返回对应的ArrayList结果*/// 返回多个对象public List<T> queryMulti(String sql, Class<T> tClass,Object... parameters){Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();List<T> query = qr.query(connection, sql,new BeanListHandler<>(tClass),parameters);return query;} catch (SQLException e) {throw new RuntimeException(e);} finally {JDBCUtilsByDruid.closeConnection(null,connection,null);}}// 返回单行结果public T querySingle(String sql,Class<T> tClass, Object... parameters){Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();T query = qr.query(connection, sql,new BeanHandler<>(tClass),parameters);return query;} catch (SQLException e) {throw new RuntimeException(e);} finally {JDBCUtilsByDruid.closeConnection(null,connection,null);}}// 返回单值结果,即单行单列public Object queryScalar(String sql,Object... parameters){Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();Object query = qr.query(connection,sql, new ScalarHandler(), parameters);return query;} catch (SQLException e) {throw new RuntimeException(e);} finally {JDBCUtilsByDruid.closeConnection(null,connection,null);}}
}

文章转载自:

http://W7gXxhdL.jqzns.cn
http://dPNrSDxF.jqzns.cn
http://PbBGkSFo.jqzns.cn
http://dwHwOhIS.jqzns.cn
http://gvk27r4L.jqzns.cn
http://OScKpjLs.jqzns.cn
http://QOKXw6zw.jqzns.cn
http://eKfJFDZ7.jqzns.cn
http://WRhf6iHR.jqzns.cn
http://J4pC0D0M.jqzns.cn
http://6xTCwDG5.jqzns.cn
http://ejGzF68T.jqzns.cn
http://oMyKMVMF.jqzns.cn
http://MtZxdMAA.jqzns.cn
http://Twvi000J.jqzns.cn
http://3ghByGab.jqzns.cn
http://jKSlo3TV.jqzns.cn
http://Dlh1yIAN.jqzns.cn
http://TjvwDUVA.jqzns.cn
http://u2JHN0mb.jqzns.cn
http://yxJm3QYs.jqzns.cn
http://F0RmeSZc.jqzns.cn
http://U3u2ymne.jqzns.cn
http://g1Pp9Oug.jqzns.cn
http://CtSHrpjd.jqzns.cn
http://44cOvz5F.jqzns.cn
http://xnndqTB0.jqzns.cn
http://auos7ZcN.jqzns.cn
http://5DQxFxPk.jqzns.cn
http://IyrKZIHY.jqzns.cn
http://www.dtcms.com/a/383088.html

相关文章:

  • 软件工程实践四:MyBatis-Plus 教程(连接、分页、查询)
  • 用 Go 快速上手 Protocol Buffers
  • Java Stream 流学习笔记
  • Linux线程id与简易封装线程实现
  • 公链分析报告 - Secret Network
  • JavaScript 简单链表题目试析
  • 【ZYNQ开发篇】Petalinux和电脑端的静态ip地址配置
  • 电商AI导购系统的模型部署架构:TensorFlow Serving在实时推荐中的实践
  • 光射三缝实验
  • K8s部署 Redis 主从集群
  • Android点击桌面图库应用启动流程trace分析
  • 【抗量子安全】全球视角下 PQC 与 QKD 技术洞察:政策引领与产业演进
  • 代码随想录学习摘抄day9(回溯1-11)
  • 数据处理指令
  • SpringBoot 中 ZK 与 Kafka 节点选择逻辑:底层原理与实践解析
  • 事务与mysql数据库锁的关系
  • 继承类模板:函数未在模板定义上下文中声明,只能通过实例化上下文中参数相关的查找找到
  • 07-Redis 基础操作全攻略:从键管理到数据类型判断
  • 【linux】特殊权限
  • [数据结构] 排序
  • Python网络与多任务编程:TCP/UDP实战指南
  • Elasticsearch面试精讲 Day 17:查询性能调优实践
  • Go-zero 构建 RPC 与 API 服务全流程
  • CRI容器运行时接口
  • 《Python 自动化表单填写全攻略:从基础操作到实战案例》
  • 黑马程序员JVM基础学习笔记
  • 驰骋低代码BPM开发平台的组成部分
  • ubuntu22.04源码安装ffmpeg-4.4
  • 黑马Java进阶教程,全面剖析Java多线程编程,并发和并行,笔记02
  • 大数据毕业设计选题推荐-基于大数据的教育与职业成功关系可视化分析系统-Spark-Hadoop-Bigdata