大数据------JavaWeb------JDBC(完整知识点汇总)

JDBC

在这里插入图片描述

  • 定义

    全称为Java数据库连接(Java DataBase Connectivity):是使用java语句来操作所有关系型数据库的一套API

  • JDBC本质

    • 它是官方定义的一套操作所有关系型数据库的规则(即接口),各个数据库厂商会去实现这套接口并提供数据库驱动的jar包,而我们可以使用这套接口(JDBD)进行编程,真正执行的代码是驱动jar包中的实现类
  • JDBC好处

    • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
    • 可随时替换底层数据库,访问数据库的Java代码基本不变(即假设我们使用MYSQL数据库则我们导入MYSQL的驱动jar包即可,同理使用其他关系型数据库时导入其他关系型数据库的驱动jar包即可)
  • JDBC步骤

    • 创建工程,导入驱动jar包(由于用的是MySQL,所以导入MySQL驱动jar包,导入步骤详见javese基础day17日志部分)
    • 注册驱动------Class.forName("com.mysql.cj.jdbc.Driver");MySQL5.0之后该步可省略,因为MySQL驱动jar包中有个java.sql.Driver文件,该文件记录了驱动全类名,在你获取数据库连接对象时会自动进行驱动注册。
    • 获取数据库连接对象Connection
    • 定义SQL语句
    • 获取执行SQL语句的对象Statement
    • 执行SQL
    • 处理返回结果
    • 释放资源

    其中创建工程,导入驱动jar包的步骤如下:

    Step1: File—>new—>Project—>Empty Project

    在这里插入图片描述

    Step2: 右键工程名—>Open Module Settings—>Project—>选择所用的JDK版本(最好为JDK1.8),然后将编译版本也设置为JDK1.8的版本

    在这里插入图片描述

    在这里插入图片描述

    Step3: 在该工程下创建模块Module,然后在该模块下创建一个lib文件夹并把MySQL驱动jar包放入—>右键jar包—>Add as Library,将该jar包设置为当前模块下有效—>OK。即可在该工程下的模块jdbc-demo中导入MySQLjar包

    在这里插入图片描述

    在这里插入图片描述

    JDBC创建工程,导入驱动jar包后的过程代码如下:

    import java.sql.*;public class TestOne {public static void main(String[] args) throws SQLException, ClassNotFoundException {// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.DriverClass.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义SQLString sql = "update account set money = 500 where id = 1";// 4.获取执行sql的对象Statement stmt = conn.createStatement();// 5.执行sqlint count = stmt.executeUpdate(sql);// 6.处理返回结果---返回的是受影响的行数System.out.println(count);// 7.释放资源stmt.close();conn.close();}
    }
    

JDBCAPI详解

DriverManager—工具类

  • 注意:该类中均是静态方法

  • 作用

    • 注册驱动
    • 获取数据库连接
  • 方法

    静态方法解释
    static void registerDriver(Driver driver)注册驱动程序
    static Connection getConnection(String url, String user, String password)尝试建立与给定数据库URL的连接。(即与建立建立连接)
    • static Connection getConnection(String url, String user, String password)参数详解

      • url:连接路径,代码格式如下

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

        2. 示例:jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai

        3. 注意

          (1)若连接的是本机的MySQL服务器则端口号默认为3306,此时代码格式为:jdbc:mysql:///数据库名称?参数键值对1&参数键值对2...

          (2)配置useSSL=false参数,作用:禁用安全连接方式,解决警告(若用安全连接方式则需要复杂配置并会降低效率)

Connection(有事务管理的方法)

  • Connection数据库连接对象的作用

    • 获取执行SQL语句的对象
    • 管理事务
  • 方法

    获取执行SQL对象的方法解释
    public Statement createStatement()创建一个 Statement对象,用于将SQL语句发送到数据库。 (普通执行SQL对象)
    public PreparedStatement prepareStatement(sql)创建一个 PreparedStatement对象,用于将参数化SQL语句发送到数据库。 (预编译SQL的执行SQL对象,以此来防止SQL注入)
    public CallableStatement prepareCall(String sql)创建一个用于调用数据库存储过程的 CallableStatement对象。 (执行存储过程的对象)
    JDBC事务管理的方法解释
    public void setAutoCommit(boolean autoCommit)开启事务。true为自动提交事务;false为手动提交事务(若设为手动提交事务即相当于开启事务)
    public void commit()提交事务
    public void rollback()回滚事务
    package at.guigu.jdbc;import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;public class TestOne {public static void main(String[] args) throws Exception{// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义SQL语句String sqlOne = "update account set money = 1000 where id = 1";String sqlTwo = "update account set money = 1000 where id = 2";// 4.获取执行sql的对象Statement stmt = conn.createStatement();//事务管理try {//开启事务conn.setAutoCommit(false);//5.1 执行sql语句int countOne = stmt.executeUpdate(sqlOne);// 6.1 处理返回结果System.out.println(countOne);//5.2 执行sql语句int countTwo = stmt.executeUpdate(sqlTwo);//6.2 处理返回结果System.out.println(countTwo);//若无异常则提交事务conn.commit();} catch (SQLException e) {//若出现异常则回滚事务e.printStackTrace();conn.rollback();}// 7.释放资源stmt.close();conn.close();}
    }
    

Statement

  • Statement作用

    执行SQL语句

  • 方法

    方法解释
    public int executeUpdate(sql)执行DML、DDL语句,返回值:若执行DML语句则返回DML语句影响的行数;若执行DDL语句则执行成功后返回的结果可能为0
    public ResultSet executeQuery(sql)执行DQL语句并返回ResultSet结果集对象
  • public int executeUpdate(sql)

    1. 执行DML语句时,若执行成功则会返回受影响的行数,若执行失败该方法通常会抛出SQLException异常,而不是返回一个特定的值
    2. 若执行DDL语句则执行成功后返回的结果可能为0,详见如下代码

    执行DDL语句成功后返回结果大于0

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;public class TestTwo {public static void main(String[] args) throws Exception{// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义DDL SQL语句String sqlOne = "CREATE DATABASE IF NOT EXISTS db2";// 4.获取执行sql的对象Statement stmt = conn.createStatement();try {//开启事务conn.setAutoCommit(false);//5.1 执行sql语句int countOne = stmt.executeUpdate(sqlOne);// 6.1 处理返回结果System.out.println(countOne);//若无异常则提交事务conn.commit();} catch (SQLException e) {//若出现异常则回滚事务e.printStackTrace();conn.rollback();}// 7.释放资源stmt.close();conn.close();}
    }
    

    在这里插入图片描述

    执行DDL语句成功后返回结果等于0

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;public class TestTwo {public static void main(String[] args) throws Exception{// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义SQL语句String sqlOne = "DROP DATABASE IF EXISTS db2";// 4.获取执行sql的对象Statement stmt = conn.createStatement();try {//开启事务conn.setAutoCommit(false);//5.1 执行sql语句int countOne = stmt.executeUpdate(sqlOne);// 6.1 处理返回结果System.out.println(countOne);//若无异常则提交事务conn.commit();} catch (SQLException e) {//若出现异常则回滚事务e.printStackTrace();conn.rollback();}// 7.释放资源stmt.close();conn.close();}
    }
    

    在这里插入图片描述

结果集对象ResultSet
  • 作用

    • 封装DQL查询语句的结果
  • 通过ResultSet类中的方法获取查询结果(其他本类方法详见API)

    方法解释
    public boolean next()将光标向前移动一行并判断当前行是否为有效行。若返回true则为有效行,代表当前行有数据;若返回false则为无效行,代表当前行没有数据
    public xxx getXxx(参数)获取参数获取数据。

    public xxx getXxx(参数)解释:

    ​ xxx:即数据类型 ; 如:int getInt(参数)String getString(参数)

    ​ 参数:

    ​ int:代表列的编号,从1开始

    ​ String:代表列的名称

    ​ 当游标移动到有效行时,此时可用int或String来充当参数以此来获取当前行指定列的数据

  • 通过结果集对象获取数据的解释

    执行DQL语句后返回的ResultSet结果集对象会将结果封装为一张表的形式且表中有一个游标(默认指向当前数据行的上一行,如图所示),所以若要查询数据则需要利用next()方法来将游标向下移动一行并判断改行是否为有效行,然后再获取数据。

    在这里插入图片描述

  • 使用步骤及代码格式

    //1.游标向下移动一行并判断该行是否有数据
    //循环判断游标是否是最后一行末尾
    while(re.next()){//获取数据:getXxx(参数)rs.getXxx(参数);
    }
    
  • 示例1:查询test02数据库中的account表的所有数据

    import java.sql.*;public class TestResultSet {public static void main(String[] args) throws Exception{// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义SQL DQL语句String sqlOne = "select * from test02.account";// 4.获取执行sql的对象Statement stmt = conn.createStatement();ResultSet rs = null;try {//开启事务conn.setAutoCommit(false);//5 执行sql语句rs = stmt.executeQuery(sqlOne);// 6 处理返回结果--即遍历re中的所有数据//6.1 循环判断游标是否是最后一行末尾while (rs.next()) {//6.2 获取数据:getXxx(参数)int id = rs.getInt(1);//等同于int id = rs.getInt("id");String name = rs.getString("name");//等同于String name = rs.getString(2);int money = rs.getInt(3);//等同于int money = rs.getInt("money");System.out.println("id:" + id + "name:" + name + "money:" + money);}//若无异常则提交事务conn.commit();} catch (SQLException e) {//若出现异常则回滚事务e.printStackTrace();conn.rollback();}// 7.释放资源rs.close();stmt.close();conn.close();}
    }
    

    在这里插入图片描述

  • 示例2:查询test02数据库中的account账户表数据并将其封装为Account对象中,最后存储到ArrayList集合中

    在这里插入图片描述

    • Step1:创建一个Account类来存放查询出来的表中的数据(一般你所创建的类名需要与你所查询的表的表名一致,目的是为了清楚知道你查询的哪个表)

      • 对于数据封装的对象一般放在名为pojo的包中(该包一般用来存放实体类)

      • Account类中的属性要求与Account表中的字段名一致

        在这里插入图片描述

    package at.guigu.pojo;public class Account {private int id;private String name;private int money;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
    }
    
    • Step2:查询account账户表数据并将其封装到该实体类的对象中去

    • Step3:将Account对象存储到ArrayList集合中

      • 注意:执行二三步的测试类不能pojo包中进行创建

        在这里插入图片描述

    • 第二三步代码如下:

    package at.guigu.jdbc;import at.guigu.pojo.Account;import java.sql.*;
    import java.util.ArrayList;public class JdbcAccount {public static void main(String[] args) throws Exception{// 1.注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3.定义SQL DQL语句String sqlOne = "select * from test02.account";// 4.获取执行sql的对象Statement stmt = conn.createStatement();ResultSet rs = null;ArrayList<Account> list = null;try {//开启事务conn.setAutoCommit(false);//5 执行sql语句rs = stmt.executeQuery(sqlOne);//6 创建ArrayList集合来存储ACccount对象list = new ArrayList<>();//7 处理返回结果--即遍历re中的所有数据//7.1 循环判断游标是否是最后一行末尾while (rs.next()) {Account account = new Account();//7.2 获取数据:getXxx(参数)int id = rs.getInt(1);//等同于int id = rs.getInt("id");String name = rs.getString("name");//等同于String name = rs.getString(2);int money = rs.getInt(3);//等同于int money = rs.getInt("money");//给对象赋值account.setId(id);account.setName(name);account.setMoney(money);list.add(account);}//若无异常则提交事务conn.commit();} catch (SQLException e) {//若出现异常则回滚事务e.printStackTrace();conn.rollback();}//查看是否将数据存入到集合中System.out.println(list);//8 释放资源rs.close();stmt.close();conn.close();}
    }
    

    在这里插入图片描述

    注意:

    ​ 页面上进行数据查询并显示出的查询数据(如下图为一个查询数据的页面)就是通过以上步骤,先查询数据然后将其封装为对应对象并将封装数据的对象存储到集合中,最后再通过某种技术来展示到页面上(后续会学习)

    在这里插入图片描述

PreparedStatement接口

  • 注意

    • 继承自Statement
    • 可通过Connection类中的public PreparedStatement prepareStatement(sql)方法来获取此接口的对象
  • 作用

    • 预防SQL注入问题(SQL注入是通过操作输入来修改事先定义好的SQL语句,以此来达到执行代码对服务器进行攻击的方法):将敏感字符进行转义

    SQL注入白话解释:

    ​ 假设一个网站需要用户名及密码才能登录,黑客攻击时随意输入完一个用户名后,此时若在密码输入框输入一行特殊的SQL语句就登录了,则登录后就会对其中的信息进行更改等危险操作

    • 预编译SQL语句并执行,性能更高
      • 预编译功能开启:useServerPreStmts=true
  • 用到的该接口中的方法

    方法解释
    public void setXxx(参数1,参数2)通过参数进行赋值。 Xxx:数据类型;如:setInt(参数1,参数2)。参数解释详见本次学习内容中的解决SQL注入部分
    public int executeUpdate()执行DML、DDL语句,返回值:若执行DML语句则返回DML语句影响的行数;若执行DDL语句则执行成功后返回的结果可能为0
    public ResultSet executeQuery()执行DQL语句并返回ResultSet结果集对象
SQL注入演示
  • SQL创建tb_user表

    DROP TABLE IF EXISTS tb_user;
    CREATE TABLE IF NOT EXISTS tb_user(id int,username VARCHAR(20),password VARCHAR(32)
    );
    INSERT INTO tb_user VALUES(1, 'zhangsan', '123'), (2, 'lisi', '123');
    SELECT * FROM tb_user;
    
  • java用户登录

    package at.guigu.jdbc;import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;public class TestSQL {public static void main(String[] args) throws Exception{Scanner input = new Scanner(System.in);// 1 注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2 获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3 接收用户输入的用户名及密码System.out.println("请输入用户名:");String name = input.next();System.out.println("请输入密码");String pwd = input.next();// 4 定义SQL语句String sql = "SELECT * FROM test02.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("登陆失败");//释放资源rs.close();stmt.close();conn.close();}
    }
    

    在这里插入图片描述

  • SQL注入代码示例—随便写的一个用户名,而密码在此处用的是特殊的SQL语句

    package at.guigu.jdbc;import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;public class TestSQL {public static void main(String[] args) throws Exception{Scanner input = new Scanner(System.in);// 1 注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2 获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3 接收用户输入的用户名及密码String name = "123nihao@";String pwd = "' or '1'='1";// 4 定义SQL语句String sql = "SELECT * FROM test02.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("登陆失败");//释放资源rs.close();stmt.close();conn.close();}
    }
    

    在这里插入图片描述

  • SQL注入发生原因

    java定义SQL语句时若要与String类型的变量进行连接则格式为'" +变量名+"',此时你在java中所写的SQL语句在SQL中会保留与String类型的变量进行连接时的单引号(即'" +变量名+"'中的''

    java定义的SQL语句如下:

    // 3 接收用户输入的用户名及密码String name = "123nihao@";String pwd = "' or '1'='1";// 4 定义SQL语句String sql = "SELECT * FROM test02.tb_user where username = '"+name+"' and password = '"+pwd+"'";
    

    其中密码' or '1'='1中的第一个单引号与'" +变量名+"'中的第一个单引号配套形成一个完整的单引号,密码' or '1'='1中的最后一个单引号与'" +变量名+"'中的最后一个单引号配套形成一个完整的单引号。则所输入的用户名和密码最终形成的SQL语句如下:

    SELECT * FROM test02.tb_user where username = '123nihao@' and password = '' or '1'='1'
    

    此时WHERE后加的条件为username = '123nihao@' and password = '' or '1'='1',其中会先执行username = '123nihao@' and password = '' 的结果然后用其结果与or '1'='1'来判断得出最后结果:username = '123nihao@' and password = ''结果为false,因为没有用户名为123nihao@的用户且密码不可能为空;而or '1'='1'结果为true,因为字符串1本来就等于其本身,所以最后where后的条件为真,此时系统则会允许查找出test02库中的tb_user表中的数据,如下图所示,在Navicat中可无障碍执行

    在这里插入图片描述

    产生如上结果的原因是:在构建动态 SQL 查询时,未对特殊字符进行转义,从而使这些字符被误解为 SQL 语句的一部分

解决SQL注入
  • 原理

    在构建动态 SQL 查询时,应该对特殊字符进行转义,以防止这些字符被误解为 SQL 语句的一部分。这样做可以确保用户输入的数据仅被解释为数据,而不是 SQL 代码。

  • 利用PreparedStatement接口进行处理,步骤如下:

    • 获取PreparedStatement对象

      // SQL语句中的参数值用?占位符替代
      String sql = "SELECT * FROM 表名 WHERE username = ? AND password = ?";
      //通过Connection获取对象并传入对应的sql语句
      PreparedStatement pstmt = conn.prepareStatement(sql);
      
    • 设置参数值—利用方法public void setXxx(参数1,参数2)

      • 参数1代表?的位置编号,从1开始
      • 参数2代表?的值
    • 执行SQL

      • 利用方法preparedStatement接口中的方法executeUpdate()executeQuery()来执行SQL语句
  • 代码示例

    package at.guigu.jdbc;import java.sql.*;
    import java.util.Scanner;public class TestSQL {public static void main(String[] args) throws Exception{Scanner input = new Scanner(System.in);// 1 注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2 获取连接对象String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3 接收用户输入的用户名及密码String name = "123nihao@";String pwd = "' or '1'='1";// 4 定义SQL语句String sql = "SELECT * FROM test02.tb_user where username = ? and password = ?";//通过Connection获取对象并传入对应的sql语句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("登陆失败");//释放资源rs.close();pstmt.close();conn.close();}
    }
    

    在这里插入图片描述

开启预编译SQL语句

预编译是在你将SQL语句传入到PreparedStatement对象时就开启了预编译,并不是在执行SQL语句时开始预编译

  • 预编译功能开启代码:useServerPreStmts=true

    • 需要将开启代码加入到DriverManager类中的static Connection getConnection(String url, String user, String password)方法中的参数url中作为参数键值对,详见代码示例
  • 代码示例

    package at.guigu.jdbc;import java.sql.*;
    import java.util.Scanner;public class TestSQL {public static void main(String[] args) throws Exception{Scanner input = new Scanner(System.in);// 1 注册驱动---该方法中的参数是驱动全类名,在驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内,即为com.mysql.cj.jdbc.Driver
    //        Class.forName("com.mysql.cj.jdbc.Driver");// 2 获取连接对象并开启预编译String url = "jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&useServerPreStmts=true;";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url, username, password);// 3 接收用户输入的用户名及密码String name = "123nihao@";String pwd = "' or '1'='1";// 4 定义SQL语句String sql = "SELECT * FROM test02.tb_user where username = ? and password = ?";//通过Connection获取对象并传入对应的sql语句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("登陆失败");//释放资源rs.close();pstmt.close();conn.close();}
    }
    

StatementPreparedStatement原理解析

在这里插入图片描述

  • Statement原理

    Java代码首先会将SQL语句发送给MySQL,然后MySQL检查SQL语法,若没问题则编译SQL(将其编译成可执行的函数),编译完成后开始执行SQL,最后返回执行结果

    • 缺点
      • Statement类的操作原理的整套流程中检查SQL语法以及编译SQL需要耗费大量时间,因为你每改变一次SQL语句则会进行一次SQL语法的检查以及SQL的编译
      • 比如上图中Statement使用的两个SQL语句中username不同,此时若执行这两条SQL语句的话则需要重复两次SQL语法的检查以及SQL的执行
  • PreparedStatement原理

    • Java代码首先会在获取PreparedStatement对象时将SQL语句发送给MySQL服务器,然后MySQL服务器检查SQL语法,若没问题则编译SQL(将其编译成可执行的函数),编译完成后将?占位符替换为具体的SQL语句开始执行SQL,最后返回执行结果
      • 优点
        • 由于使用?占位符来代替你要更改的SQL语句来查找数据,所以不需要频繁的对Java中的SQL语句进行更改,这也就代表SQL语法的检查以及SQL编译都只需进行一次,之后只需将占位符替换为你要的SQL语句即可执行SQL(原因是:SQL模板一样,不一样的部分用?占位符代替,所以只需要进行一次检查和编译
        • 比如上图中PreparedStatement使用的SQL语句中,用?占位符来替代不同的username,此时系统会只进行一次SQLSQL语法的检查以及SQL编译,在编译完成之后在将username的值传入进行SQL的执行
        • 若要使性能更高则可开启预编译功能,详见本节开启预编译SQL语句

数据库连接池

在这里插入图片描述

  • 简介
    • 它是一个容器(即集合),负责分配、管理数据库连接。数据库连接池中的为提前申请的数据库连接
    • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个,当使用完毕之后则会将其归还给数据库连接池,供其他的应用程序重复使用
    • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
      • 解释:假设数据库连接池中的数据库连接目前已经被用户全部占用,此时若有一个新用户要使用数据库连接,则该新用户就属于被遗漏了。当新用户被遗漏时,数据库连接池会去判断其他用户是否在占用资源时未进行任何操作,若存在此情况,则会强制将该用户的数据库连接给断开并归还到数据库连接池中,此时被遗漏的新用户即可使用该数据库连接
  • 作用
    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏

数据库连接池的实现

  • 标准接口:DataSource------所有的连接池技术都要实现该接口
    • 此为官方(SUN)提供的数据库连接池标准接口,需要第三方组织来实现该接口
    • 功能:获取连接
    • 该接口中获取连接的方法------public Connection getConnection()
  • 常见的数据库连接池------都实现了DataSource接口,且都需利用public Connection getConnection()方法来获取连接
    • DBCP
    • C3P0
    • Driud(德鲁伊)
      • 该连接池是阿里巴巴开源的数据库连接池项目
      • 功能强大,性能优秀,是Java语言最好的数据库连接池之一
Driud(德鲁伊)数据库连接池
  • 使用步骤

    • 导入jar包druid-1.1.12.jar

    • 定义配置文件------druid.properties

    • 加载配置文件

    • 获取数据库连接池对象

    • 获取数据库连接

    import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.util.Properties;public class DruidOne {public static void main(String[] args) throws Exception {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("Jdbc-demo/src/druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connection conn = dataSource.getConnection();System.out.println(conn);}
    }
    

    在这里插入图片描述

  • Druid配置文件详解

    #driverClassName代表数据库驱动,后跟驱动全类名(在MySQL驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内)
    driverClassName=com.mysql.cj.jdbc.Driver
    # 数据库连接URL
    url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    # 数据库用户名
    username=root
    # 数据库密码
    password=123456
    # 初始化连接数量---即容器中初始的数据库连接数量
    initialSize=5
    # 最大活跃连接数量---容器中初始为5个,但若5个用完了,此时可以在申请5个数据库连接数量
    #也就是说容器中最多存放10个数据库连接
    maxActive=10
    # 获取连接时的最大等待时间,单位:毫秒。---与数据库进行连接时若超过3s仍未连接成功,则会报错
    maxWait=3000
    #最小空闲连接数量---minIdle=5
    # 配置检测连接是否有效的SQL,可以是一个查询语句,如果不指定则默认为"SELECT 1"---validationQuery=SELECT 1
    # 是否开启自动提交事务---defaultAutoCommit=true
    
    属性解释备注
    url数据库的JDBC连接地址,一般为连接Oracle/MySQL。格式为:jdbc:mysql://ip:port/dbname?option1&option2...如:url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username登录数据库的用户名
    password登录数据库的用户密码
    initialSize启动程序时,在连接池中初始化多少个连接10-50已足够
    maxActive连接池中最多支持多少个活动会话
    maxWait程序向连接池中申请连接超时,超过maxWait的值后,认为本次请求失败,即连接池没有可用连接。单位:毫秒建议值为:100。设置为-1时表示无限等待
    minEvictableIdleTimeMillis池中某个连接的空闲时长达到N毫秒后,连接池在下次检查空闲连接时会将其断开连接(即回收该连接),单位:毫秒该时间设置要小于防火墙超时设置net.netfilter.nf_conntrack_tcp_timeout_established的设置值
    timeBetweenEvictionRunsMillis检查空闲连接的频率,若为非正整数时表示不进行检查。单位:毫秒
    keepAlive程序没有close连接且空闲时长超过minEvictableIdleTimeMillis则会执行validationQuery指定的SQL,以保证该程序连接不会被杀掉,其范围不会超过minldle指定的连接个数建议值为true
    minldle回收空闲连接时将保证至少有minldle个连接initialSize相同
    removeAbandoned要求程序从池中get到连接后,N秒必须close,否则druid会强制回收该连接,不管该连接中是活动还是空闲,以防进程不会进行close而霸占连接正常close连接时设置为true
    removeAbandonedTimeout设置druid强制回收连接的时限,当程序从池中get到连接开始算起,超过此值后,druid将强制回收该连接,单位:秒应大于业务运行最长时间
    logAbandoned当druid强制回收连接后,是否将stack trace记录到日志中默认为false,建议为true
    testWhileIdle当程序请求连接,池在分配连接时,是否先检查该连接是否有效(该检查比较高效)默认为false,建议为true
    validationQuery检查从连接池获取的数据库连接是否仍然有效的SQL查询语句。Druid会连接到数据库执行该SQL,若正常返回则表示连接可用;反之则表示不可用
    testOnBorrow程序申请连接时进行连接的有效性检查(该检查比较低效,影响性能)默认为false
    testOnReturn程序返还连接时进行连接有效性检查(该检查比较低效,影响性能)默认为false
    poolPreparedStatements缓存通过以下两个方法发起的SQL语句:public PreparedStatement prepareStatement(String sql)public PreparedStatement prepareStatement(String sql,int resultSetType, int resultSetConcurrency)默认为false,建议为true
    maxPoolPrepareStatementPerConnectionSize每个数据库连接最多缓存多少个SQL语句建议为20
    filters这里配置的是插件,常用的插件有如下几种:监控统计: filter:stat日志监控: filter:log4j 或者 slf4j防御SQL注入: filter:wall建议为stat``,wall,slf4j
    connectProperties指定连接属性。它是一个键值对的形式,可以设置一些数据库连接的额外属性。

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

  • 需要完成的操作如下:

    • 查询:查询所有数据
    • 添加:添加品牌
    • 修改:根据id修改
    • 删除:根据id删除
  • 完成该例题的准备工作如下:

    • 准备环境
      • 建立商品的数据库表,表名为tb_brand
      • 设置数据库连接池
      • 写出实体类Brand
    • 写出测试用例

环境准备

  • 创建商品数据库表

    DROP TABLE IF EXISTS tb_brand;-- 创建品牌表brand
    CREATE TABLE IF NOT EXISTS 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);SELECT * FROM tb_brand;
    

    注意:一些不需要顾客添加数据的字段需要设置为自增,比如id

  • 设置数据库连接池

    #driverClassName代表数据库驱动,后跟驱动全类名(在MySQL驱动jar包下的META-INF下的services文件夹下的java.sql.Driver文件内)
    driverClassName=com.mysql.cj.jdbc.Driver
    # 数据库连接URL
    url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    # 数据库用户名
    username=root
    # 数据库密码
    password=123456
    # 初始化连接数量---即容器中初始的数据库连接数量
    initialSize=5
    # 最大活跃连接数量---容器中初始为5个,但若5个用完了,此时可以在申请5个数据库连接数量
    #也就是说容器中最多存放10个数据库连接
    maxActive=10
    # 获取连接时的最大等待时间,单位:毫秒。---与数据库进行连接时若超过3s仍未连接成功,则会报错
    maxWait=3000
    #最小空闲连接数量---minIdle=5
    # 配置检测连接是否有效的SQL,可以是一个查询语句,如果不指定则默认为"SELECT 1"---validationQuery=SELECT 1
    # 是否开启自动提交事务---defaultAutoCommit=true
    
  • 写出实体类Brand

    • 注意事项
      • 由于需要将数据库表brand中的字段写到Brand实体类中,一次写一次比较麻烦,所以可以直接选中数据库中的SQL创建表的SQL语句中的字段将其复制到idea中,然后用快捷键Ctrl+Shift+Alt:idea同时操作多行来进行属性的定义,这样更快更便捷
      • 数据库中的基本数据类型在实体类中建议使用包装类(原因两点:第一,包装类的默认值均为null;第二,以字段status为例,数据库中定义为int类型,0代表禁用,若在java中直接定义为int类型,由于int默认值为0,则会自动将其status设置为0,所以需要用其包装类)
    package at.guigu.example;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 Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {this.id = id;this.brandName = brandName;this.companyName = companyName;this.ordered = ordered;this.description = description;this.status = 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 +'}';}
    }
    

写出测试用例

例题1:查询数据库表tb_brand的所有数据

  • 查询所有数据步骤

    • 获取Connection连接对象

      • 加载配置文件
      • 获取连接池对象
      • 获取数据库Connection连接
    • 定义SQL:select * from tb_brand

    • 获取PreparedStatement对象

    • 设置参数:不需要

    • 执行SQL

      • 由于查询数据属于DQL SQL语句,所以需要利用PreparedStatement接口中的executeQuery()方法来执行SQL语句,并返回Result结果集对象
    • 处理结果:List<Brand>

      • 当查询所有数据时由于结果很多,所以可将一个个的结果封装到集合中去,在经过特殊方法展现到页面上,步骤如下:

        Step1:获取数据

        Step2:将数据封装为Brand对象

        Step3:装载集合

    • 释放资源

  • 查询所有数据代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import org.junit.Test;
    import javax.sql.DataSource;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;public class TestOne {/*** 查询所有数据*/@Testpublic void methodOne() throws Exception{//1 获取Connection连接对象//1.1 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("F:/node/idea/Jdbc/Jdbc-demo/src/druid.properties"));//1.2 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//1.3 获取数据库Connection连接对象Connection conn = dataSource.getConnection();//2 定义SQL语句String sql = "SELECT * FROM tb_brand";//3 通过Connection连接对象获取PreparedStatement对象并传入即将要执行的SQL语句PreparedStatement pstmt = conn.prepareStatement(sql);/*4 设置参数---此处不需要pstmt.setString(int, String);*///5 执行传入PreparedStatement对象的SQL语句ResultSet rs = pstmt.executeQuery();//6 处理结果List<Brand> list = new ArrayList<>();while (rs.next()) {//6.1 获取数据---获取数据时参数要与数据库表中的字段名一致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");//6.2 将数据封装为Brand对象Brand brand = new Brand(id, brandName, companyName, ordered, description, status);//6.3 装载集合list.add(brand);}//打印集合for (Brand brand : list) {System.out.println(brand);}//7 释放资源rs.close();pstmt.close();conn.close();}
    }
    

    在这里插入图片描述

例题2:向数据库表tb_brand中添加数据

  • 添加数据步骤

    • 接受页面提交的参数
    • 获取Connection连接对象
      • 加载配置文件
      • 获取连接池对象
      • 获取数据库Connection连接
    • 定义SQL:INSERT INTO tb_brand(brand_name, company_name, ordered, description, status) vALUES (?, ?, ?, ?, ?);
    • 获取PreparedStatement对象
    • 设置参数—设置除了id之外的所有字段
    • 执行SQL
      • 由于添加数据属于DML SQL语句,所以需要利用PreparedStatement接口中的executeUpdate()方法来执行SQL语句,并返回执行结果影响的行数
    • 处理结果—返回布尔类型
      • 若影响的行数大于0则代表执行成功;反之,执行失败
    • 释放资源
      • 注意:增删改没有ResultSet对象,所以释放资源时不用释放该对象
  • 添加数据代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import org.junit.Test;
    import javax.sql.DataSource;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;public class TestOne {/*** 添加数据*/@Testpublic void methodTwo() throws Exception{//1 接收页面提交的参数String brandName = "香飘飘";String companyName = "香飘飘";int ordered = 1;String description = "绕地球一圈";int status = 1;//2 获取Connection连接对象//2.1 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("F:/node/idea/Jdbc/Jdbc-demo/src/druid.properties"));//2.2 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//2.3 获取数据库Connection连接对象Connection conn = dataSource.getConnection();//3 定义SQL语句String sql = "INSERT INTO tb_brand(brand_name, company_name, ordered, description, status) vALUES (?, ?, ?, ?, ?);";//4 通过Connection连接对象获取PreparedStatement对象并传入即将要执行的SQL语句PreparedStatement pstmt = conn.prepareStatement(sql);//5 设置参数---设置除了id之外的所有字段pstmt.setString(1, brandName);pstmt.setString(2, companyName);pstmt.setInt(3, ordered);pstmt.setString(4, description);pstmt.setInt(5, status);//6 执行传入PreparedStatement对象的SQL语句int count = pstmt.executeUpdate();// count代表影响的行数//7 处理结果---若为true则执行成功;反之则执行失败System.out.println(count > 0);//8 释放资源pstmt.close();conn.close();}
    }
    

    在这里插入图片描述

例题3:修改数据库表tb_brand的数据

注意:修改数据时,虽然未对id进行操作,但是是根据id修改数据库表tb_brand中的数据的,所以在你对数据进行修改时,系统会自动返回一个对应的id,该id对应了数据库表中修改数据所在行的id

  • 修改数据步骤

    • 接受页面提交的参数
    • 获取Connection连接对象
      • 加载配置文件
      • 获取连接池对象
      • 获取数据库Connection连接
    • 定义SQL:UPDATE tb_brand SET brand_name = ?, company_name = ?, ordered = ?, description = ?, status = ? WHERE id = ?;
    • 获取PreparedStatement对象
    • 设置参数—需要数据库表tb_brand的所有字段
    • 执行SQL
      • 由于添加数据属于DML SQL语句,所以需要利用PreparedStatement接口中的executeUpdate()方法来执行SQL语句,并返回执行结果影响的行数
    • 处理结果—返回布尔类型
      • 若影响的行数大于0则代表执行成功;反之,执行失败
    • 释放资源
      • 注意:增删改没有ResultSet对象,所以释放资源时不用释放该对象
  • 修改数据代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import org.junit.Test;
    import javax.sql.DataSource;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;public class TestOne {/*** 修改数据*/@Testpublic void methodThree() throws Exception{//1 接收页面提交的参数int id = 4;String brandName = "香飘飘";String companyName = "飘飘";int ordered = 15;String description = "真香真奶茶";int status = 1;//2 获取Connection连接对象//2.1 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("F:/node/idea/Jdbc/Jdbc-demo/src/druid.properties"));//2.2 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//2.3 获取数据库Connection连接对象Connection conn = dataSource.getConnection();//3 定义SQL语句String sql = "UPDATE tb_brand SET brand_name = ?, company_name = ?, ordered = ?, description = ?, status = ? WHERE id = ?;";//4 通过Connection连接对象获取PreparedStatement对象并传入即将要执行的SQL语句PreparedStatement pstmt = conn.prepareStatement(sql);//5 设置参数---设置除了id之外的所有字段pstmt.setString(1, brandName);pstmt.setString(2, companyName);pstmt.setInt(3, ordered);pstmt.setString(4, description);pstmt.setInt(5, status);pstmt.setInt(6, id);//6 执行传入PreparedStatement对象的SQL语句int count = pstmt.executeUpdate();// count代表影响的行数//7 处理结果---若为true则执行成功;反之则执行失败System.out.println(count > 0);//8 释放资源pstmt.close();conn.close();}
    }
    

    在这里插入图片描述

例题4:删除数据库表tb_brand中的数据

注意:删除数据时,虽然未对id进行操作,但是在数据库表中是根据id进行数据的删除,所以在删除数据时系统会返回你所删除的数据所在的id

  • 删除数据步骤

    • 接受页面提交的参数
    • 获取Connection连接对象
      • 加载配置文件
      • 获取连接池对象
      • 获取数据库Connection连接
    • 定义SQL:DELETE FROM tb_brand WHERE id = ?;
    • 获取PreparedStatement对象
    • 设置参数—需要数据库表tb_brand的所有字段
    • 执行SQL
      • 由于添加数据属于DML SQL语句,所以需要利用PreparedStatement接口中的executeUpdate()方法来执行SQL语句,并返回执行结果影响的行数
    • 处理结果—返回布尔类型
      • 若影响的行数大于0则代表执行成功;反之,执行失败
    • 释放资源
      • 注意:增删改没有ResultSet对象,所以释放资源时不用释放该对象
  • 删除数据代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import org.junit.Test;
    import javax.sql.DataSource;
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;public class TestOne {/*** 删除表中数据*/@Testpublic void methodFour() throws Exception{//1 接收页面提交的参数int id = 4;//2 获取Connection连接对象//2.1 加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("F:/node/idea/Jdbc/Jdbc-demo/src/druid.properties"));//2.2 获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//2.3 获取数据库Connection连接对象Connection conn = dataSource.getConnection();//3 定义SQL语句String sql = "DELETE FROM tb_brand WHERE id = ?;";//4 通过Connection连接对象获取PreparedStatement对象并传入即将要执行的SQL语句PreparedStatement pstmt = conn.prepareStatement(sql);//5 设置参数---设置除了id之外的所有字段pstmt.setInt(1, id);//6 执行传入PreparedStatement对象的SQL语句int count = pstmt.executeUpdate();// count代表影响的行数//7 处理结果---若为true则执行成功;反之则执行失败System.out.println(count > 0);//8 释放资源pstmt.close();conn.close();}
    }
    

    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day 16 Linux服务管理和日志管理

服务管理 启动服务&#xff1a;systemctl start 服务名 停止服务&#xff1a;systemctl stop 服务名 重启服务&#xff1a;systemctl restart 服务名 重新加载配置文件&#xff1a;systemctl reload 服务名&#xff08;期间并不停止服务进程&#xff09; 查看服务运行状态…

pycharm/idea专业版过期永久解决

1、在file-settings-plungins中找到设置 2、点击增加如图网址3、下载安装此插件 4、按照如下步骤操作即可 5、如果又过期了重复4步骤即可&#xff0c;idea编辑器也是如此操作

如何用ChatGPT进行论文撰写?

原文链接&#xff1a;如何用ChatGPT进行论文撰写&#xff1f;https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601619&idx1&snb686fbe87dedfac2df3a6afe780b2ffe&chksmfa820c34cdf5852251dca64597024ea62ddbde280086535ec251f4b62b848d9f9234688384e6…

深度学习 Lecture 9 信息增益、One-hot、回归树、集成树、随机森林、XGBoost模型

一、信息增益&#xff08;Information Gain) 决定使用什么特征来划分一个节点取决于什么样的特征选择最能减少熵&#xff08;也就是使纯度最大化&#xff09; 在决策树中&#xff0c;熵的减少被称为信息增益。 所以如何选择呢&#xff1f; 假设现在有三个特征可以选择&#…

政安晨:【深度学习神经网络基础】(十一)—— 激活函数的导数以及在反向传播中的应用

目录 线性激活函数的导数 Softmax激活函数的导数 S型激活函数的导数 双曲正切激活函数的导数 ReLU激活函数的导数 如何在反向传播中应用 批量训练和在线训练 随机梯度下降 反向传播权重更新 选择学习率和动量 Nesterov动量 政安晨的个人主页&#xff1a;政安晨 欢迎…

Go 语言中的 GIF 图像处理完全指南:`image/gif`的技术与实践

Go 语言中的 GIF 图像处理完全指南&#xff1a;image/gif的技术与实践 概述安装与基础设置导入 image/gif 包初步配置示例&#xff1a;设置一个简单的 GIF 编码环境 读取与解码 GIF 图像读取 GIF 文件解析 GIF 数据 创建与编码 GIF 图像创建 GIF 图像编码 GIF 图像 处理 GIF 动…

中文编程入门(Lua5.4.6中文版)第十二章 Lua 协程 参考《愿神》游戏

在《愿神》的提瓦特大陆上&#xff0c;每一位冒险者都拥有自己的独特力量——“神之眼”&#xff0c;他们借助元素之力探索广袤的世界&#xff0c;解决谜题&#xff0c;战胜敌人。而在提瓦特的科技树中&#xff0c;存在着一项名为“协同程序”的高级秘术&#xff0c;它使冒险者…

使用Canal同步MySQL 8到ES中小白配置教程

&#x1f680; 使用Canal同步MySQL 8到ES中小白配置教程 &#x1f680; 文章目录 &#x1f680; 使用Canal同步MySQL 8到ES中小白配置教程 &#x1f680;**摘要****引言****正文**&#x1f4d8; 第1章&#xff1a;初识Canal1.1 Canal概述1.2 工作原理解析 &#x1f4d8; 第2章&…

企业网站制作如何被百度收录

1、网站在百度中的整体评分 说俗点就是网站的权重&#xff0c;在优化过程中我们会见到很多网站出现秒收的情况&#xff0c;发布的文章几分钟就可以收录&#xff0c;这个通过SITE语法都可以去查询&#xff0c;那么这跟自己的网站权重以及内容更新习惯是有非常重要的关联。 我们…

Real3DPortrait照片对口型,数字人,音频/视频驱动数字人

先看效果 上传一张图片和一段音频&#xff0c;照片如下&#xff1a; 合成后效果如下&#xff1a; 照片对口型-音频驱动 支持音频驱动和视频驱动&#xff0c;视频可以使照片有参照视频中的口型和和动作。 项目地址 https://github.com/yerfor/Real3DPortrait 我的环境 win…

PVE grub resue错误修复 lvmid BUG

服务器断电后启动不起来&#xff0c;显示grub resue 找了半天没有找到修复方法。看官方文档有一处Recovering from grub “disk not found” error when booting from LVM 极为类似。https://pve.proxmox.com/wiki/Recover_From_Grub_Failure 下面是处理过程。 使用PVE 6.4启…

单例模式详解

什么是单例模式 首先&#xff0c;单例模式是一种设计模式&#xff0c;按字面意思&#xff0c;指一个类只能创建一个对象&#xff0c;当创建出多个对象的时候&#xff0c;就会出现报错异常 单例模式为何出现&#xff1f; 1.资源共享:某些情况下&#xff0c;多个对象都需要共享一…

双向链表也叫双链表

双向链表也叫双链表 双向链表也叫双链表 每个节点都有两个指针&#xff0c;分别指向 直接前驱节点、直接后继节点 双向链表中任意一个节点&#xff0c;都可以通过通过它的前驱节点和后继节点&#xff0c;访问其他节点 节点如下 节点定义 ListNode // 节点的值 T element; /…

康谋技术 | 深入探讨:自动驾驶中的相机标定技术

随着自动驾驶技术的快速发展&#xff0c;多传感器的数据采集和融合可以显著提高系统的冗余度和容错性&#xff0c;进而保证决策的快速性和正确性。在项目开发迭代过程中&#xff0c;传感器标定扮演着至关重要的角色&#xff0c;它位于数据采集平台与感知融合算法之间&#xff0…

【R语言】混合图:小提琴图+箱线图

{ggstatsplot} 是 {ggplot2} 包的扩展&#xff0c;用于创建图形&#xff0c;其中包含信息丰富的绘图本身中包含的统计测试的详细信息。在典型的探索性数据分析工作流程中&#xff0c;数据可视化和统计建模是两个不同的阶段&#xff1a;可视化通知建模&#xff0c;而建模又可以建…

【FreeRTOS】使用CubeMX快速移植FreeRTOS工程到蓝桥杯开发板(STM32G431RBT6)

使用CubeMX快速创建FreeRTOS工程到蓝桥杯开发板&#xff08;STM32G431RBT6&#xff09; CubeMX配置CubeMX基础工程的配置☆FreeRTOS相关配置FreeRTOS配置选项卡的解释 软件工程架构与程序设计小综合&#xff1a;任务的创建删除、挂起与恢复设计cubexMX配置创建任务软件程序设计…

工业自动化,3D视觉技术3C薄片自动化上料

随着制造业的快速发展&#xff0c;3C行业对薄片类零件的上料需求日益增长。传统的上料方式往往依赖于人工操作&#xff0c;效率低下且存在误差。为了解决这一问题&#xff0c;3D视觉技术应运而生&#xff0c;为3C薄片自动化上料提供了强大的技术支持。本文将探讨3D视觉技术如何…

HarmonyOS开发实例:【分布式手写板】

介绍 本篇Codelab使用设备管理及分布式键值数据库能力&#xff0c;实现多设备之间手写板应用拉起及同步书写内容的功能。操作流程&#xff1a; 设备连接同一无线网络&#xff0c;安装分布式手写板应用。进入应用&#xff0c;点击允许使用多设备协同&#xff0c;点击主页上查询…

stm32f103c8t6学习笔记(学习B站up江科大自化协)-SPI

SPI通信 SPI&#xff0c;&#xff08;serial peripheral interface&#xff09;&#xff0c;字面翻译是串行外设接口&#xff0c;是一种通用的数据总线&#xff0c;适用于主控和外挂芯片之间的通信&#xff0c;与IIC应用领域非常相似。 IIC无论是在硬件电路还是在软件时序设计…

Covalent Network(CQT)宣布推出面向 Cronos 生态的捐赠计划与 API 积分,为 Web3 创新赋能

为了促进 Web3 领域的创新&#xff0c;Covalent Network&#xff08;CQT&#xff09;宣布将其捐赠计划向 Cronos 生态系统中的开发者拓展。这一战略性举措&#xff0c;旨在通过向 Cronos 网络中基于 Covalent Network&#xff08;CQT&#xff09;API 构建的项目提供支持和资源&…