JDBC 核心 API

引入 mysql-jdbc 驱动 jar

驱动 jar 版本选择:8.0.27

MySQL 版本推荐驱动版本备注
MySQL 5.5.x5.0.xcom.mysql.jdbc.Driver
MySQL 5.7.x5.1.xcom.mysql.jdbc.Driver
MySQL 8.x8.0.x建议 8.0.25+ 省略时区设置,com.mysql.cj.jdbc.Driver

Java 工程导入依赖:

  1. 项目创建 lib 文件夹
  2. 导入驱动依赖 jar 包
  3. jar 包右键-添加为项目依赖

JDBC 基本使用步骤分析(6 步)

  1. 注册驱动:依赖的 jar 包,进行安装
  2. 获取连接:connection 建立连接
  3. 创建发送 SQL 语句对象:创建发送 SQL 语句的 statement
  4. 发送 SQL 语句,并获取返回结果:statement 发送 SQL 语句到数据库,并且取得返回结构
  5. 结果集解析:将 result 结果解析出来
  6. 资源关闭:释放 resultsetstatementconnection

基于 statement 演示查询

  • 准备数据库数据
CREATE DATABASE atguigu;
 
USE atguigu;
 
CREATE TABLE t_user (
   id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户主键',
   account VARCHAR(20) NOT NULL UNIQUE COMMENT '账号',
   PASSWORD VARCHAR(64) NOT NULL COMMENT '密码',
   nickname VARCHAR(20) NOT NULL COMMENT '昵称');
   
INSERT INTO t_user(account,PASSWORD,nickname) VALUES
  ('root','123456','经理'),('admin','666666','管理员');
  • 基于 statement 实现查询
/**
 * @Author 赵伟风
 * Description: 利用 JDBC 技术,完成用户数据查询工作
 *
 * 步骤总结 (6步)
 *    1. 注册驱动
 *    2. 获取连接
 *    3. 创建 statement
 *    4. 发送 SQL 语句,并获取结果
 *    5. 结果集解析
 *    6. 关闭资源
 */
 
package com.ate.api.statement;
 
import com.mysql.cj.jdbc.Driver;
 
import java.sql.*;
import java.util.StringJoiner;
 
public class statementqury {
    public static void  main(String[] args) throws SQLException {
		// 1. 注册驱动
        // 导入依赖:8+ 版本的驱动要带 cj
        DriverManager.registerDriver(new Driver());
 
        // 2. 获取连接:connection
		// jdbc:数据库名://ip:port/数据库名
		// java.sql 接口 = 实现类
		Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/atguigu", "root", "0128");
 
        // 3. 创建 statement
        Statement statement = connection.createStatement();
 
        // 4. 发送 SQL,获取返回结果
        String sql = "select * from t_user;";
        ResultSet resultset = statement.executeQuery(sql);
 
        // 5. 进行结果集解析
        while (resultset.next()) {
            int id = resultset.getInt("id"); // get 后面加调用的列的类型
            String account = resultset.getString("account");
            String password = resultset.getString("password");
            String nickname = resultset.getString("nickname");
            System.out.println(id + "--" + account + "--" + password + "--" + nickname);
        }
 
        // 6. 关闭资源:先打开的后关
        // 打开顺序:connection -> statement -> resultset
        // 关闭顺序:resutset -> statement -> connection
        resultset.close();
        statement.close();
        connection.close();
    }
}

基于 statement 方式问题

  • 类加载知识补充

    【Java类加载机制 - CSDN App】http://t.csdnimg.cn/Hfe8X

    类加载:就是将类的class文件读入内存,并创建一个Java.lang.class对象。类在运行期第一次使用时,首先会被类加载器动态加载至JVM。类的加载过程又分为了五个阶段:加载、验证、准备、解析、初始化。为了方便记忆可以编为一个口诀:家(加载)宴(验证)准备(准备)了西(解析)式(初始化)菜。
    
     类的生命周期被分为了七个阶段:加载、验证、准备、解析、初始化、使用、限载
    
  • 基于statement实现模拟登录

/**
 * @Author 赵伟风
 * Description: 输入账号密码,模拟用户登录!
 */
public class JdbcStatementLoginPart {
 
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
 
        //1.输入账号和密码
        Scanner scanner = new Scanner(System.in);
        String account = scanner.nextLine();
        String password = scanner.nextLine();
        scanner.close();
 
        //2.jdbc的查询使用
        /**
         * 类加载: java文件 -> 编译 -> 【 class字节码文件 -->  类加载 --> jvm虚拟中  --> Class对象】
         * 类加载具体步骤:  加载 【class文件转成对象加载到虚拟机中】->
         *                连接 【验证(检查类文件) -> 准备 (静态变量赋默认值) -> 解析 (调用静态代码块) 】 ->
         *                初始化 -> (赋真实值)
         * 以下7种方式会触发类加载:
         *new指令:程序创建一个类的实例对象时\n\ngetstatic指令:当程序访问类的静态变量时\n\nputstatic指令:当程序给静态变量赋值时\n\n
         *invokestatic指令:当程序调用静态方法时\n\n注:程序访问类的静态常量不会触发类加载机制
         *    1. new关键字
         *    2. 调用静态属性
         *    3. 调用静态方法
         *    4. 接口 包含1.8 新特性 default关键字
         *    5. 反射 【Class.forName() 类名.class】
         *    6. 子类调用会触发父类的静态代码块
         *    7. 触发类的入口方法main
         */
         
         //1:DriverManager.registerDriver(new Driver());调用两次。不用
         //2:new Driver()  频繁修改不优雅
        //注册一次驱动 方法三
        Class.forName("com.mysql.cj.jdbc.Driver");
 
 
 
        /**获取数据库连接
         * 重写: 为了子类扩展父类的方法!父类也间接的规范了子类方法的参数和返回!
         * 重载: 重载一般应用在第三方的工具类上,为了方便用户多种方式传递参数形式!简化形式!
         */
        /**
         * 三个参数:
         *    String URL: 连接数据库地址
         *    String user: 连接数据库用户名
         *    String password: 连接数据库用户对应的密码
         * 数据库URL语法:
         *    JDBC:
         *        ip port
         *        jdbc:mysql | jdbc:oracle :// 127.0.0.1 | localhost : 3306 / 数据库名
         *        jdbc:mysql://localhost:3306/day01
         *        192.168.33.45
         *        jdbc:mysql://192.168.33.45/3306/day01
         *        当前电脑的省略写法! 注意:本机和端口3306
         *        jdbc:mysql://localhost:3306/day01 = jdbc:mysql:///day01
         *
         * 两个参数:
         *     String URL : 写法还是jdbc的路径写法!
         *     Properties : 就是一个参数封装容器!至少要包含 user / password key!存储连接账号信息!
         *
         * 一个参数:
         *    String URL: URl可以携带目标地址,可以通过?分割,在后面key=value&key=value形式传递参数
         *                jdbc:mysql:///day01?user=root&password=123456
         * 扩展路径参数(了解):
         *    serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
         *
         */
        //获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "root");
 
        //固定方法固定剂
        //创建statement
        Statement statement = connection.createStatement();
 
        //执行SQL语句 [动态SQL语句,需要字符串拼接]
        String sql = "select * from t_user where account = '"+account+"' and password = '"+password+"' ;";
 
 
        /**
         *  ResultSet 结果集对象 = executeQuery(DQL语句)
         *  int响应行数  = executeUpdate(非DQL语句)
         */
        ResultSet resultSet = statement.executeQuery(sql);
 
 
        //ResultSet == 小海豚  你必须有面向对象的思维:Java是面向对象编程的语言 OOP!
        /**
         *
         * TODO:1.需要理解ResultSet的数据结构和小海豚查询出来的是一样,需要在脑子里构建结果表!
         * TODO:2.有一个光标指向的操作数据行,默认指向第一行的上边!我们需要移动光标,指向行,在获取列即可!
         *        boolean = next()
         *              false: 没有数据,也不移动了!
         *              true:  有更多行,并且移动到下一行!
         *       推荐:推荐使用if 或者 while循环,嵌套next方法,循环和判断体内获取数据!
         *       if(next()){获取列的数据!} ||  while(next()){获取列的数据!}
         *
         *TODO:3.获取当前行列的数据!
         *         get类型(int columnIndex | String columnLabel)
         *        列名获取  //lable 如果没有别名,等于列名, 有别名label就是别名,他就是查询结果的标识!
         *        列的角标  //从左到右 从1开始! 数据库全是从1开始!
         */
 
        //进行结果集对象解析
        if (resultSet.next()){
            //只要向下移动,就是有数据 就是登录成功!
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
 
        //关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
 
}
  • 存在问题
    1. SQL语句需要字符串拼接,比较麻烦(示例代码在:执行SQL语句 [动态SQL语句,需要字符串拼接])
    2. 只能拼接字符串类型,其他的数据库类型无法处理
    3. 可能发生注入攻击

动态值充当了 SQL 语句结构,影响了原有的查询结果!