JDBC基础

数据库 ------ 基础

      • [1. JDBC](#1. JDBC)
      • [2. SQL 注入](#2. SQL 注入)
      • [3. 模拟登录功能](#3. 模拟登录功能)
          • [3.1 数据库连接池](#3.1 数据库连接池)
          • [3.2 创建数据库连接工具类](#3.2 创建数据库连接工具类)
          • [3.3 登录模拟实现](#3.3 登录模拟实现)

1. JDBC

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| JDBC:(Java DataBase Connectivity)Java数据库连接,Java编程语言中用于执行与数据库交互的API;Java和数据库之间的纽带 数据库驱动:指连接(Java)程序与不同类型的数据库之间的软件组件 Driver接口:Driver接口由各大数据库厂商提供各自对应的Driver接口 Connection接口:用于与数据库建立连接的对象,与数据库进行通信,并执行各种数据库操作 Statement接口: JDBC 中用于执行静态 SQL 语句并返回结果的对象 ResultSet接口: JDBC 中用于表示 SQL 查询结果集的对象 JDBC的使用步骤:加载JDBC驱动程序 🡺 建立数据库连接Connection 🡺 创建执行SQL的语句Statement 🡺 处理执行结果ResultSet 🡺 释放资源 |

  • ➤ JDBC使用步骤
java 复制代码
package jdcb;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * JDBC 查询操作
 */
public class Demo01_Bases {
    public static void main(String[] args) throws Exception {
        // 早期版本:Class.forName("com.mysql.jdbc.Driver");
        // 1. 加载驱动程序(jdk6及以上的版本此处可省略,DriverManager集成了Driver的自动注册)
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2. 建立连接
        String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&CharacterEncoding=utf8";
        String userName = "root";
        String passWord = "123456";
        Connection connection = DriverManager.getConnection(url, userName, passWord);

        // 3. 创建Statement对象
        Statement statement = connection.createStatement();

        // 4. 执行SQL语句
        ResultSet resultSet = statement.executeQuery("select * from student limit 4;");

        // 5. 处理结果
        while (resultSet.next()){
            System.out.print(resultSet.getString("name") + "\t");
            System.out.print(resultSet.getInt("age") + "\t");
            System.out.print(resultSet.getString("gender") + "\t");
            System.out.println(resultSet.getString("birth"));
        }

        // 6. 释放资源(先创建后关闭)
        resultSet.close();
        statement.close();
        connection.close();
    }
}
  • ▶ url 解析
text 复制代码
 String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&CharacterEncoding=utf8"

jdbc:mysql://:表示使用 JDBC 连接 MySQL 数据库
localhost:3306:表示 MySQL 数据库所在的主机和端口号
school:表示要连接的数据库名称
serverTimezone=Asia/Shanghai:表示服务器时区为亚洲/上海,用于确保时间日期相关操作的正确性
CharacterEncoding=utf8:表示字符编码为 UTF-8,用于确保传输中文等非 ASCII 字符时的正确性

  • ➤ JDBC接口及使用方法
  • ➤ 将查询结果存入字典
java 复制代码
package jdcb;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JDBC 查询操作
 */
public class Demo01_Bases {
    public static void main(String[] args) throws Exception {
        // 早期版本:Class.forName("com.mysql.jdbc.Driver");
        // 1. 加载驱动程序(jdk6及以上的版本此处可省略,DriverManager集成了Driver的自动注册)
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2. 建立连接
        String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&CharacterEncoding=utf8";
        String userName = "root";
        String passWord = "123456";
        Connection connection = DriverManager.getConnection(url, userName, passWord);

        // 3. 创建Statement对象
        Statement statement = connection.createStatement();

        // 4. 执行SQL语句
        ResultSet resultSet = statement.executeQuery("select * from student limit 4;");

        // 5. 处理结果
        List<Map<String, Object>> list = new ArrayList<>();
        while (resultSet.next()){
            Map<String, Object> map = new HashMap<>();
            map.put("name",resultSet.getString("name"));
            map.put("age",resultSet.getInt("age"));
            map.put("gender",resultSet.getString("gender"));
            map.put("birth",resultSet.getString("birth"));
            list.add(map);
        }
        list.forEach(System.out::println);

        // 6. 释放资源(先创建后关闭)
        resultSet.close();
        statement.close();
        connection.close();
    }
}

2. SQL 注入

|--------------------------------------------------------------------------------------------------------------------------|
| SQL 注入: 一种常见的安全漏洞(攻击者通过恶意构造的输入,向应用程序的数据库发出未经授权的查询或执行操作) 危害:攻击者可以利用 SQL 注入漏洞来绕过应用程序的身份验证、获取敏感数据、修改数据,甚至执行任意的数据库命令 |

  • ➤ SQL 注入
java 复制代码
String username = request.getParameter("username");
String password = request.getParameter("password");
String query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";

如在以上输入 ' OR '1'='1,将会导致原始的查询被修改为 SELECT * FROM users WHERE username='' OR '1'='1' AND password='' OR '1'='1',这将返回所有用户的记录,从而绕过身份验证

  • ➤ 使用预编译语句但不使用参数化查询
java 复制代码
String username = request.getParameter("username");
String password = request.getParameter("password");
String query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
PreparedStatement statement = connection.prepareStatement(query);

参数化查询(Prepared Statement)

通过使用预编译语句和绑定参数的方式,可以确保用户输入被视为数据值而不是 SQL 代码,这样可以防止攻击者注入恶意的 SQL 语句

  • ➤ 参数化查询
java 复制代码
package jdcb;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JDBC 查询操作
 */
public class Demo01_Bases {
    public static void main(String[] args) throws Exception {
        // 早期版本:Class.forName("com.mysql.jdbc.Driver");
        // 1. 加载驱动程序(jdk6及以上的版本此处可省略,DriverManager集成了Driver的自动注册)
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2. 建立连接
        String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&CharacterEncoding=utf8";
        String userName = "root";
        String passWord = "123456";
        Connection connection = DriverManager.getConnection(url, userName, passWord);

        // 3. sql预编译
        String sql = "select name,age,gender,birth from student where gender=? limit 4;";
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setString(1,"男");

        // 4. 执行SQL语句
        ResultSet resultSet = ps.executeQuery();

        // 5. 处理结果
        List<Map<String, Object>> list = new ArrayList<>();
        while (resultSet.next()){
            Map<String, Object> map = new HashMap<>();
            map.put("name",resultSet.getString("name"));
            map.put("age",resultSet.getInt("age"));
            map.put("gender",resultSet.getString("gender"));
            map.put("birth",resultSet.getString("birth"));
            list.add(map);
        }
        list.forEach(System.out::println);

        // 6. 释放资源(先创建后关闭)
        resultSet.close();
        ps.close();
        connection.close();
    }
}
java 复制代码
package jdcb;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Demo02_Update {
    public static void main(String[] args) throws Exception{
        // 1. 加载驱动程序(jdk6及以上的版本此处可省略,DriverManager集成了Driver的自动注册)
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2. 建立连接
        String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&CharacterEncoding=utf8";
        String userName = "root";
        String passWord = "123456";
        Connection connection = DriverManager.getConnection(url, userName, passWord);

        // 3. sql预编译
        String sql = "insert into student(name,age,gender,job,birth) values (?,?,?,?,?)";
        PreparedStatement ps = connection.prepareStatement(sql);
        // 赋值
        ps.setString(1,"何伟");
        ps.setInt(2,22);
        ps.setString(3,"男");
        ps.setString(4,"学生");
        ps.setString(5,"2001-01-05");

        // 4. 执行失去了语句
        int rows = ps.executeUpdate();
        System.out.println(rows);

        // 5. 释放资源(先创建后关闭)
        ps.close();
        connection.close();
    }
}

3. 模拟登录功能

3.1 数据库连接池

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 数据库连接池:一种用于管理和维护数据库连接的技术 作用:负责创建、分配、回收和监控数据库连接 原理:通过预先创建一定数量的数据库连接并将其保存在连接池中,以便在需要时可以快速获取和释放连接 意义:以减少每次请求时创建和销毁连接的开销,提高数据库操作的性能和效率 常见数据库连接池:Apache Commons DBCP,HikariCP,Druid,Tomcat JDBC Pool |

传统JDBC

使用JDBC进行数据库的操作(增删改查)时,需要经过复杂的过程才能完成

建立TCP/IP连接(三次握手) 🢂 数据库连接认证 🢂 SQL语句执行并返回结果 🢂 数据库关闭 🢂 TCP/IP连接断开(四次挥手)

如果大量的用户同时对数据库进行相关业务的访问时,将会造成数据库在创建连接,断开连接等基础操作中浪费大量内存开销,导致服务器的资源利用不恰当,甚至会发生服务器内存溢出,造成应用的使用卡顿,发生宕机等故障

而连接池避免频繁地创建和销毁数据库连接,节省了时间和资源,并且可以减轻数据库服务器的负担,提高系统的性能和稳定性,从而满足更多用户的需求

3.2 创建数据库连接工具类

JDBC创建

java 复制代码
		String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url, username, password);

HikariCP连接池创建

在所需项目resource目录下创建hikari.properties文件

在hikari.properties文件添加连接属性

text 复制代码
jdbcUrl=jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai&characterEncoding=utf8
dataSource.user=root
dataSource.password=123456
java 复制代码
 private static HikariDataSource dataSource;
    // 数据库连接池
    static {
        // 加载配置文件
        HikariConfig config = new HikariConfig("/hikari.properties");
        // 创建数据源对象(通过此对象获取连接)
        dataSource = new HikariDataSource(config);
    }
    // 从HikariPool中获取连接
    public static Connection getHikariConnection() throws SQLException {
        return dataSource.getConnection();
    }
3.3 登录模拟实现
  • 创建maven项目Login
  • 在pom.xml文件中添加mysql数据库和HikariCP数据库连接池依赖
xml 复制代码
<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>4.0.2</version>
        </dependency>
    </dependencies>
  • 创建hikari.properties文件
yaml 复制代码
jdbcUrl=jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf8
dataSource.user=root
dataSource.password=123456
  • 在项目中创建包和类util.DBUtil
java 复制代码
package util;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBUtil {
    // **************************************************由数据库创建连接**************************************************
    public static Connection getConnection() throws SQLException {
        String url = "jdbc:mysql://localhost:3306/school?serverTimezone=Asia/Shanghai&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        return DriverManager.getConnection(url, username, password);
    }

    // **************************************************由连接池创建连接**************************************************
    private static HikariDataSource dataSource;

    // 数据库连接池
    static {
        // 加载配置文件
        HikariConfig config = new HikariConfig("/hikari.properties");
        // 创建数据源对象(通过此对象获取连接)
        dataSource = new HikariDataSource(config);
    }

    // 从HikariPool中获取连接
    public static Connection getHikariConnection() throws SQLException {
        return dataSource.getConnection();
    }
}
  • 在数据库MySQL中创建表
sql 复制代码
create database if not exists school charset = utf8;
use school;

-- 登录
create table if not exists login
(
    id       bigint primary key auto_increment comment '主键ID',
    username varchar(20) not null comment '用户名',
    password varchar(20) not null comment '密码'
) charset = utf8;
insert into login(username, password)
values ('lyc', '123456');
  • 创建登录类
java 复制代码
import util.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

public class Regin {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String userName = scanner.nextLine();
        System.out.print("请输入密码:");
        String passWord = scanner.nextLine();

        try {
            // 简单模拟直接使用JDBC连接
            Connection connection = DBUtil.getConnection();
            // Connection connection = DBUtil.getHikariConnection(); // 连接池创建连接
            String sql = "select id from login where username=? and password=?";
            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setString(1,userName);
            ps.setString(2,passWord);
            ResultSet rs = ps.executeQuery();

            if (rs.next()){
                System.out.println("登录成功!");
            }else {
                System.out.println("用户名或密码错误!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}
相关推荐
蓝染-惣右介1 分钟前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
小林想被监督学习2 分钟前
idea怎么打开两个窗口,运行两个项目
java·ide·intellij-idea
HoneyMoose4 分钟前
IDEA 2024.3 版本更新主要功能介绍
java·ide·intellij-idea
我只会发热6 分钟前
Java SE 与 Java EE:基础与进阶的探索之旅
java·开发语言·java-ee
是老余7 分钟前
本地可运行,jar包运行错误【解决实例】:通过IDEA的maven package打包多模块项目
java·maven·intellij-idea·jar
crazy_wsp8 分钟前
IDEA怎么定位java类所用maven依赖版本及引用位置
java·maven·intellij-idea
.Ayang10 分钟前
tomcat 后台部署 war 包 getshell
java·计算机网络·安全·web安全·网络安全·tomcat·网络攻击模型
bjzhang7515 分钟前
SpringBoot开发——Maven多模块工程最佳实践及详细示例
spring boot·maven·maven多模块工程
一直学习永不止步15 分钟前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
hummhumm29 分钟前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j