JDBC - (02)JDBC的核心


image-20230206074352715

JDBC -(02)JDBC的核心

实验环境

Java:17

MySQL:8.0.26

JDBC:8.0.30

IDEA:2022

1. 引入 mysql-jdbc 驱动 jar

驱动下载地址:https://downloads.mysql.com/archives/c-j/

1.1 驱动版本的选择

mysql版本推荐驱动版本备注
mysql 5.5.x5.0.xcom.mysql.jdbc.Driver
mysql 5.7.x5.1.xcom.mysql.jdbc.Driver
mysql 8.x8.0.xcom.mysql.cj.jdbc.Driver(建议使用8.0.25+,不用设置时区)

1.2 Java 工程导入依赖

1.项目创建lib文件夹

image-20230314151939465

2.导入驱动依赖 jar 包

image-20230314152108814

3.jar 包右键-添加项目依赖

image-20230314152203365

image-20230314152223689

此时导入的驱动依赖

image-20230314152323754

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

2.1 基本使用步骤

1.注册驱动

2.获取连接

3.创建发送 sql 语句对象

4.发送 sql 语句,并获取返回结果

5.结果集解析

6.资源关闭

image-20230314153317775

2.2 应用举例

案例:获取数据库julissa中t_user表中的用户信息

public class QueryUsers {
    public static void main(String[] args) throws SQLException {

        //1.注册驱动
        DriverManager.deregisterDriver(new Driver());
        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa","root","123456");
        //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");
            String account = resultSet.getString("account");
            String password = resultSet.getString("password");
            String nickname = resultSet.getString("nickname");
            System.out.println(id + "--" + account + "--" + password + "--" + nickname);
        }
        //6.关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

3. 基于statement实现查询

3.1 准备数据库数据

1.创建t_user表

image-20230314155529424

2.添加数据

image-20230314155634711

3.2 查询目标

查询全部用户信息进行控制台输出

image-20230314155834475

3.3 基于statement实现查询

代码实现:

package com.julissa.api.statement;

import com.mysql.cj.jdbc.Driver;

import java.sql.*;

/**
 *
 * TODO:
 *  DriverManager
 *  Connection
 *  Statement
 *  ResultSet
 */
public class QueryUsers {
    public static void main(String[] args) throws SQLException {

        //1.注册驱动
        /**
         * TODO:
         *  注册驱动 DriverManager.deregisterDrivercom.mysql.cj.jdbc.Driver)
         *  依赖:驱动版本 8+ com.mysql.cj.jdbc.Driver
         *      驱动版本 5+ com.mysql.jdbc.Driver
         */
        DriverManager.deregisterDriver(new Driver());
        //2.获取连接
        /**
         * TODO:
         *  Java程序要和数据库创建连接
         *  Java程序连接数据库,肯定是调用某个方法,方法也需要填入连接数据库的基本信息
         *      数据库ip地址:127.0.0.1
         *      数据库端口号:3306
         *      账号:root
         *      密码:123456
         *      连接数据库名称:julissa
         */

        /**
         * 参数:
         *  参数1:url jdbc:数据库厂商名://ip地址:port/数据库名
         *              jdbc:mysql://localhost:3306/julissa
         *  参数2:username 数据库软件的账号 root
         *  参数3:password 数据库软件的密码 123456
         */
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa","root","123456");
        //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");
            String account = resultSet.getString("account");
            String password = resultSet.getString("password");
            String nickname = resultSet.getString("nickname");
            System.out.println(id + "--" + account + "--" + password + "--" + nickname);
        }
        //6.关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

执行结果:

image-20230314163129168

3.4 总结

3.4.1 注册驱动
DriverManager.deregisterDriver(new Driver)

image-20230315031939750

驱动有两种,根据导入的驱动jar包选择对应的驱动

  • 驱动版本 8+ com.mysql.cj.jdbc.Driver
  • 驱动版本 5+ com.mysql.jdbc.Driver
3.4.2 获取连接

Java程序要和数据库创建连接,肯定是调用某个方法,方法也需要填入连接数据库的基本信息

  • 数据库ip地址
  • 数据库端口号
  • 账号
  • 密码
  • 连接数据库名称
Connection connection = DriverManager.getConnection(url,user,password);

DriverManager.getConnection()方法中需要提供三个参数:

  • 参数1:url jdbc:数据库厂商名://ip地址:port/数据库名,比如:jdbc:mysql://localhost:3306/julissa

  • 参数2:user 数据库软件的账号,比如:root

  • 参数3:password 数据库软件的密码 ,比如:123456

4. 基于statement方式的问题

明确jdbc流程和详细使用

发现问题,引出prepareStatement

4.1 准备数据库数据

和第三小节的数据库一样

image-20230314155634711

4.2 查询目标

模拟登陆,控制台输入账号和密码,判断是否登陆成功

image-20230315061211702

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2XsybwT-1678879201972)(null)]

4.3 基于statement实现查询

package com.julissa.api.statement;

import com.mysql.cj.jdbc.Driver;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * TODO:
 *      输入账号和密码
 *      进行数据库信息查询(t_user)
 *      反馈登陆成功还是失败
 *
 *  TODO:
 *      1.键盘输入事件,收集账号和密码信息
 *      2.注册驱动
 *      3.获取连接
 *      4.创建statement对象
 *      5.发送sql语句,并获取结果集
 *      6.解析结果集,进行判断,显示登陆成功还是失败
 *      7.关闭资源
 */
public class UserLogin {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Scanner scanner = new Scanner(System.in);
        //1.接收数据
        System.out.println("请输入账号:");
        String account = scanner.next();
        System.out.println("请输入密码:");
        String password = scanner.next();

        //2.注册驱动
        /**
         *  TODO:
         *      注意:
         *          注册驱动 DriverManager.deregisterDrivercom.mysql.cj.jdbc.Driver);
         *              依赖:驱动版本 8+ com.mysql.cj.jdbc.Driver
         *                   驱动版本 5+ com.mysql.jdbc.Driver
         *      问题:注册两次驱动
         *          1.DriverManager.deregisterDriver() 方法本身会注册一次
         *          2.Driver static { DriverManager.deregisterDriver() } 静态代码块,也会注册一次
         *      解决:只想注册一次
         *          只触发静态代码块代码即可
         *       触发静态代码块:
         *          类加载进制:类加载的时候,会触发静态代码块
         *              加载 [class文件 -> JVM虚拟机的class对象]
         *              连接 [验证(检查文件类型) -> 准备(静态变量默认值) ->解析(触发静态代码块)]
         *              初始化(给静态属性赋真实值)
         *       触发类加载:
         *          1.new 关键字
         *          2.调用静态方法
         *          3.调用静态属性
         *          4.接口,1.8 defaulut默认实现
         *          5.反射
         *          6.子类触发父类
         *          7.程序入门main
         *
         */

        //方案1
        //DriverManager.deregisterDriver(new Driver());

        //方案2 固定写法,mysql新版本驱动 切换数据库,oracle驱动,得改代码
        //new Driver();

        //方案3 通过反射,触发类加载,触发静态代码块的调用
        //字符串 -> 提取到外部配置文件 -> 可以在不改变代码的情况下,完成数据库驱动的切换
        Class.forName("com.mysql.cj.jdbc.Driver");

        //3.获取数据库连接
        /**
         *
         * getConnection(1,2,3)是一个重载方法
         * 允许开发着用不同的形式传入数据库连接的核心参数
         *
         * 核心属性:
         *      1.数据库软件所在的主机ip地址:127.0.0.1 | localhost
         *      2.数据库软件所在的主机的端口号: 3306
         *      3.连接的具体库: julissa
         *      4.连接的账号: root
         *      5.连接的密码: 123456
         *      6.可选的信息:没有
         *
         *  三个参数:
         *      String url        数据库软件所在的具体地址,所在的端口号以及连接的具体库,可选信息
         *                        语法:jdbc:数据库管理软件名称(mysql | oracle)://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
         *                          jdbc:mysql://127.0.0.1:3306/julissa
         *                          jdbc:mysql://localhost:3306/julissa
         *                          本机的省略写法: jdbc:mysql:///julissa  省略了【本机地址】和【默认端口3306】,必须是本机和3306端口才可以省略
         *      String user       数据库的账号  root
         *      String password   数据库的密码  123456
         *  两个参数:
         *      String url         和三个参数的url作用一样  jdbc:mysql://127.0.0.1:3306/julissa
         *      Properties info     存储账号和密码
         *                           Properties 类似与 Map,只不过 key 和 value 都是字符串形式
         *                           key user  账号信息
         *                           key password 密码信息
         *  一个参数:
         *      String url         数据库ip,端口号,具体的数据库,可选信息(账号密码)
         *                          jdbc:数据库管理软件名称://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
         *                          jdbc:mysql://localhost:3306/julissa?user=root&password=123456
         *                          携带固定的参数名 user 和 password 传递账号和密码信息
         *
         *
         *   url路径可选信息:
         *      url?key=value&key=value
         *      url?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai
         *      useUnicode 是否使用Unicode字符集
         *      characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk 或UTF8
         *      autoReconnect  当数据库连接异常中断时,是否自动重新连接?
         *      connectTimeout  和数据库服务器建立socket连接时的超时,单位:毫秒。
         *      serverTimezone 时区设置功能有UTC,Asia/Shanghai,Asia/Hongkong
         *
         *      8.0.25 版本以后,自动识别时区 serverTimezone=Asia/Shanghai可省略,之前版本还是需要添加的
         *      8版本之后,默认使用utf-8字符集,useUnicode=true&characterEncoding=UTF8可省略
          */
        //方案1:三个参数
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");

        //方案2:两个参数
//        Properties info = new Properties();
//        info.put("user","root");
//        info.put("password","123456");
//        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", info);

        //方案3:一个参数
        //Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?user=root&password=123456");


        //4.创建发送sql语句的statement对象
        //statement 可以发送sql语句到数据库,并且获取返回结果
        Statement statement = connection.createStatement();

        //5.发送sql语句,获取返回结果(编写sql语句,发送sql语句)
        String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
        ResultSet resultSet = statement.executeQuery(sql);

        //6.结果集解析
        /**
         *
         * Java是一种面向对象的思维,把查询结果封装成ResultSet对象,里面有行有列
         *  resultSet -> 逐行获取数据,行 -> 行的列的数据**
         *  想要进行数据解析,我们需要进行两件事情:**
         *	    1.移动游标指定获取数据
         * 	    2.获取指定数据行的的列的数据
         *  游标移动问题:
         * 	    resultSet内部包含一个游标,指定当前行数据
         * 	    默认游标指向第一行数据之前
         *      我们可以调用next()方向向下移动一行游标
         * 	    如果我们有很多行数据,可以使用while(resultSet.next){获取每一行的数据}
         * 	    boolean = next() ,next方法返回值为布尔类型
         * 	         true:有更多行数据,并且向下移动一行
         * 	         false:没有更多行数据,不移动
         *  获取列数据问题:
         *      获取光标指向的行的列的数据
         *	    resultSet.get类型(String columLabel | int columIndex)
         * 	        columLabel: 列名,如果有别名,可以写别名
         * 	        columIndex: 列的小角标获取(从左到右 从1开始)
         */
//        while (resultSet.next()){
//            System.out.println("账号:" + resultSet.getString("account"));
//            System.out.println("密码:" + resultSet.getString("password"));
//            System.out.println("昵称:" + resultSet.getString("nickname"));
//
//        }
        //移动一次游标,如果有数据,就代表登陆成功
        if(resultSet.next()){
            System.out.println("登陆成功!");
            System.out.println("账号:" + resultSet.getString("account"));
            System.out.println("密码:" + resultSet.getString("password"));
            System.out.println("昵称:" + resultSet.getString("nickname"));
        }else {
            System.out.println("登陆失败~~~");
        }
        //7.关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

4.4 总结

4.4.1 注册驱动

如果我们在程序中写入以下代码,那么会产生什么问题呢?

DriverManager.deregisterDriver(new Driver());

问题:注册两次驱动

  • DriverManager.deregisterDriver() 方法本身会注册一次
  • Driver static { DriverManager.deregisterDriver() } 静态代码块,也会注册一次

image-20230315033709475

image-20230315033757792

解决:只想注册一次
只触发静态代码块代码即可

触发静态代码块:
类加载进制:类加载的时候,会触发静态代码块
加载 [class文件 -> JVM虚拟机的class对象]
连接 [验证(检查文件类型) -> 准备(静态变量默认值) ->解析(触发静态代码块)]
初始化(给静态属性赋真实值)

触发类加载:
1.new 关键字
2.调用静态方法
3.调用静态属性
4.接口,1.8 defaulut默认实现
5.反射
6.子类触发父类
7.程序入门main

改进后的注册驱动代码:

​ 通过反射,触发类加载,触发静态代码块的调用

//字符串 -> 提取到外部配置文件 -> 可以在不改变代码的情况下,完成数据库驱动的切换
//通过反射注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");

4.4.2 获取数据库连接

image-20230315040555414

getConnection(1,2,3)是一个重载方法,允许开发着用不同的形式传入数据库连接的核心参数

核心属性:
1.数据库软件所在的主机ip地址:127.0.0.1 | localhost
2.数据库软件所在的主机的端口号: 3306
3.连接的具体库: julissa
4.连接的账号: root
5.连接的密码: 123456
6.可选的信息:没有

(1)三个参数:
String url 数据库软件所在的具体地址,所在的端口号以及连接的具体库,可选信息
语法:jdbc:数据库管理软件名称(mysql | oracle)😕/数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
jdbc:mysql://127.0.0.1:3306/julissa
jdbc:mysql://localhost:3306/julissa
本机的省略写法: jdbc:mysql:///julissa 省略了【本机地址】和【默认端口3306】,必须是本机和3306端口才可以省略
String user 数据库的账号 root
String password 数据库的密码 123456

//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");

(2)两个参数

String url 和三个参数的url作用一样 jdbc:mysql://127.0.0.1:3306/julissa
Properties info 存储账号和密码
Properties 类似与 Map,只不过 key 和 value 都是字符串形式
key user 账号信息
key password 密码信息

//创建用于存储账号密码的properties对象
Properties info = new Properties();
info.put("user","root");
info.put("password","123456");
//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", info);

(3)一个参数

String url 数据库ip,端口号,具体的数据库,可选信息(账号密码)
jdbc:数据库管理软件名称://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
jdbc:mysql://localhost:3306/julissa?user=root&password=123456
携带固定的参数名 user 和 password 传递账号和密码信息

//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?user=root&password=123456");

url路径可选信息:
url?key=value&key=value
useUnicode 是否使用Unicode字符集
characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk 或UTF8
autoReconnect 当数据库连接异常中断时,是否自动重新连接?
connectTimeout 和数据库服务器建立socket连接时的超时,单位:毫秒。
serverTimezone 时区设置功能有UTC,Asia/Shanghai,Asia/Hongkong

​ 8.0.25 版本以后,自动识别时区 serverTimezone=Asia/Shanghai可省略,之前版本还是需要添加的
​ 8版本之后,默认使用utf-8字符集,useUnicode=true&characterEncoding=UTF8可省略

//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai", "root", "123456");
4.4.3 创建statement对象

statement 可以发送sql语句到数据库,并且获取返回结果

//创建statement对象
Statement statement = connection.createStatement();
4.4.4 发送sql语句,获取返回结果

编写sql语句,发送sql语句到数据库,获取返回结果

SQL分类:

  • DDL 容器创建、修改、删除
  • DML 数据插入、修改、删除
  • DQL 数据查询
  • DCL 权限控制
  • TPL 事务控制

executeUpdate() 和 executeQuery() 的选择

方法参数返回值
statement.executeUpdate()sql(非DQL)int,情况1:DML 返回影响的行数,例如,删除三条数据 return 3 ,添加两条数据 return 2;情况2:非DML return 0
statement.executeQuery()sql(DQL)ResultSet,结果集
//编写sql语句
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
//发送sql语句并获取返回结果集
ResultSet resultSet = statement.executeQuery(sql);
4.4.5 解析结果集

Java是一种面向对象的思维,把查询结果封装成ResultSet对象,里面有行有列

resultSet -> 逐行获取数据,行 -> 行的列的数据

想要进行数据解析,我们需要进行两件事情:

​ 1.移动游标指定获取数据行

​ 2.获取指定数据行的的列的数据

游标移动问题:

​ resultSet内部包含一个游标,指定当前行数据
​ 默认游标指向第一行数据之前
​ 我们可以调用next()方向向下移动一行游标
​ 如果我们有很多行数据,可以使用while(resultSet.next){获取每一行的数据}

​ boolean = next() ,next方法返回值为布尔类型

​ true:有更多行数据,并且向下移动一行
​ false:没有更多行数据,不移动

获取列数据问题:

​ 获取光标指向的行的列的数据

​ resultSet.get类型(String columLabel | int columIndex)
​ columLabel: 列名,如果有别名,可以写别名
​ columIndex: 列的小角标获取(从左到右 从1开始)

假设结果集中有如下数据:

idaccuntpasswordnickname
1root123456经理
2admin666666管理员

结果集的数据解析:

image-20230315054427234

//移动一次游标,如果有数据,就代表登陆成功
if(resultSet.next()){
    System.out.println("登陆成功!");
    System.out.println("账号:" + resultSet.getString("account"));
    System.out.println("密码:" + resultSet.getString("password"));
    System.out.println("昵称:" + resultSet.getString("nickname"));
}else {
    System.out.println("登陆失败~~~");
}
4.5.6 关闭资源
//7.关闭资源
resultSet.close();
statement.close();
connection.close();

4.5 存在的问题

1.sql语句需要字符串拼接,会很麻烦

2.只能拼接字符串类型,其他的数据类型无法处理

3.可能发生注入攻击

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

假设sql查询语句如下:

String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";

当用户输入account:root

password:'or ‘1’='1

拼接后的sql语句:

select * from t_user where account = 'root'  and password = ''or '1'='1'

就会查询出账号为root的用户

5.基于prepareStatement方式实现查询

利用prepareStatement解决上述注入攻击和sql语句拼接问题

5.1 基于prepareStatement方式实现查询

package com.julissa.api.statement;

import java.sql.*;
import java.util.Scanner;

public class UserLogin_V2 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入账号:");
        String account = scanner.next();
        System.out.println("请输入密码:");
        String password = scanner.next();

        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2..获取数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");

        /**
         *
         *  statement
         *      1.创建statement
         *      2.编写sql语句
         *      3.发送sql语句,获取返回结果
         *
         *   prepareStatement
         *      1.编写sql语句,动态值部分使用占位符 ? 替代
         *      2.创建prepareStatement,并且传入sql语句
         *      3.动态值 占位符 ? 赋值 单独赋值即可
         *      4.发生sql语句,获取返回结果
         */

        //3.编写sql语句
        String sql = "select * from t_user where account = ? and password = ?";

        //4.创建预编译statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //5.给动态值赋值
        /**
         *  参数1:index 占位符的位置 从左向右 从1开始
         *  参数2:object 可以设置任何类型的数据,避免了我们拼接和类型更加丰富
         */
        preparedStatement.setString(1, account);
        preparedStatement.setString(2, password);

        //6.执行sql语句,并获取返回结果
        //statement.executeQuery(sql) | statement.executeUpdate(sql)
        //preparedStatement.executeQuery() | preparedStatement.executeUpdate() TODO:不需要再传入sql,因为它已经知道了动态值
        ResultSet resultSet = preparedStatement.executeQuery();

        //7.判读是否登陆成功
        if(resultSet.next()){
            System.out.println("登陆成功!");
            System.out.println("账号:" + resultSet.getString("account"));
            System.out.println("密码:" + resultSet.getString("password"));
            System.out.println("昵称:" + resultSet.getString("nickname"));
        }else {
            System.out.println("登陆失败!");
        }

        //8.释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

5.2 statement 和 prepareStatement 的区别

image-20230315080300459

statement的流程:
1.创建statement
2.编写sql语句
3.发送sql语句,获取返回结果

//创建发送sql语句的statement对象
Statement statement = connection.createStatement();

//编写sql语句
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";

//发送sql语句,获取返回结果(编写sql语句,发送sql语句
ResultSet resultSet = statement.executeQuery(sql);

prepareStatement的流程:
1.编写sql语句,动态值部分使用占位符 ? 替代
2.创建prepareStatement,并且传入sql语句
3.动态值 占位符 ? 赋值 单独赋值即可
4.发生sql语句,获取返回结果

//编写sql语句
String sql = "select * from t_user where account = ? and password = ?";

//创建预编译statement
PreparedStatement preparedStatement = connection.prepareStatement(sql);

//给动态值赋值
/**
*  参数1:index 占位符的位置 从左向右 从1开始
*  参数2:object 可以设置任何类型的数据,避免了我们拼接和类型更加丰富
*/
preparedStatement.setString(1, account);
preparedStatement.setString(2, password);

//执行sql语句,并获取返回结果
ResultSet resultSet = preparedStatement.executeQuery();

6.基于prepareStatement方式实现增删改(DML)

6.1 添加操作

@Test
public void testInsert() throws ClassNotFoundException, SQLException {
    /**
         * 向t_user表插入一条数据
         * account test
         * password test123
         * nickname 测试人员
         */
    String account = "test";
    String password = "test123";
    String nickname = "测试人员";

    //1.注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    //2.获取数据库连接
    Connection connection = DriverManager.getConnection
        ("jdbc:mysql://localhost:3306/julissa","root","123456");
    //3.编写sql
    String sql = "insert into t_user(account,password,nickname) values(?,?,?)";
    //4.创建预编译statement,并传入sql语句
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //5.给动态值设置值
    preparedStatement.setString(1,account);
    preparedStatement.setString(2,password);
    preparedStatement.setString(3,nickname);
    //6.执行sql语句,并获取返回结果
    int i = preparedStatement.executeUpdate();
    //7.判读是否插入成功 1成功
    if(i != 1) {
        System.out.println("插入数据失败");
    }else {
        System.out.println("插入数据成功");
    }
    //8.关闭资源
    preparedStatement.close();
    connection.close();
}

6.2 修改操作

@Test
public void testUpdate() throws ClassNotFoundException, SQLException {
    /**
         * 修改t_user表中admin用户的密码
         * account admin
         * password admin123
         **/
    String account = "admin";
    String password = "admin123";

    //1.注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    //2.获取数据库连接
    Connection connection = DriverManager.getConnection
        ("jdbc:mysql://localhost:3306/julissa","root","123456");
    //3.编写sql
    String sql = "update t_user set password=? where account=?";
    //4.创建预编译statement,并传入sql语句
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //5.给动态值设置值
    preparedStatement.setString(1,password);
    preparedStatement.setString(2,account);
    //6.执行sql语句,并获取返回结果
    int i = preparedStatement.executeUpdate();
    //7.判读是否插入成功 1成功
    if(i != 1) {
        System.out.println("修改数据失败");
    }else {
        System.out.println("修改数据成功");
    }
    //8.关闭资源
    preparedStatement.close();
    connection.close();
}

6.3 删除操作

@Test
public void testDelete() throws ClassNotFoundException, SQLException {
    /**
         * 删除t_user表中id为3的用户信息
         * id 3
         */
    String id = "3";

    //1.注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    //2.获取数据库连接
    Connection connection = DriverManager.getConnection
        ("jdbc:mysql://localhost:3306/julissa","root","123456");
    //3.编写sql
    String sql = "delete from t_user where id=?";
    //4.创建预编译statement,并传入sql语句
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //5.给动态值设置值
    preparedStatement.setString(1,id);
    //6.执行sql语句,并获取返回结果
    int i = preparedStatement.executeUpdate();
    //7.判读是否插入成功 1
    if(i != 1) {
        System.out.println("修改数据失败");
    }else {
        System.out.println("修改数据成功");
    }
    //8.关闭资源
    preparedStatement.close();
    connection.close();
}

6.4 查询操作

@Test
public void testSelect() throws ClassNotFoundException, SQLException {
   		 /**
         *
         * 目标:查询t_user表中所有用户信息,并且封装到一个List<Map> List集合中
         *
         * 解释:
         *      行: id account password nickname
         *      行: id account password nickname
         *      行: id account password nickname
         *
         * 数据库 -> resultSet -> java -> map(key=列名,value=列的内容) -> List<Map> -> List
         */

    //1.注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    //2.获取数据库连接
    Connection connection = DriverManager.getConnection
        ("jdbc:mysql://localhost:3306/julissa","root","123456");
    //3.编写sql
    String sql = "select id,account,password,nickname from t_user";
    //4.创建预编译statement,并传入sql语句
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    //5.执行sql语句,并获取返回结果
    ResultSet resultSet = preparedStatement.executeQuery();
    //6.解析结果集
    List<Map> list = new ArrayList<>();

    //获取列的信息对象
    //TODO:metaData装的当前结果集列的对象,(可以根据列的下表获取列的名称,获取列的数量)
    ResultSetMetaData metaData = resultSet.getMetaData();

    //获取列的数量
    int columnCount = metaData.getColumnCount();

    while (resultSet.next()) {
        Map<String,Object> map = new HashMap<>();

        //手动取值
        //map.put("id",resultSet.getString("id"));
        //map.put("account",resultSet.getString("account"));
        //map.put("password",resultSet.getString("password"));
        //map.put("nickname",resultSet.getString("nickname"));

        //自动遍历列,从1开始
        for (int i = 1; i <= columnCount; i++) {
            //根据指定下标获取值
            Object value = resultSet.getObject(i);
            //获取指定列的名称
            //getColumnLabel:会获取别名,如果没有再获取列名
            String key = metaData.getColumnLabel(i);
            map.put(key,value);
        }
        list.add(map);
    }
    //遍历集合
    for (Map map:
         list) {
        System.out.println(map);
    }
    //7.关闭资源
    resultSet.close();
    preparedStatement.close();
    connection.close();
}

image-20230315092121171

7.prepareStatement使用方式总结

7.1 使用步骤总结

1.注册驱动
2.获取连接
3.编写SQL语句结构
4.创建prepareStatement对象。传入SQL语句
5.占位符赋值
6.发送SQL语句,获取返回结果
7.解析结果集
8.关闭资源n

7.2 使用API总结

7.2.1 注册驱动
  • 方案1:调用静态方法,但是会注册两次驱动

    DriverManager.deregisterDriver(new Driver());

  • 方案2:反射触发

    Class.forName(“com.mysql.cj.jdbc.Driver”);

7.2.2 获取连接

Connection connection = DriverManager.getConnection();

  • 三个参数:DriverManager.getConnection(String url,String user,String password)

  • 两个参数:DriverManager.getConnection(String url,Properties info)

    info 有两个key : user 和 password

  • 一个参数:DriverManager.getConnection(String url)

​ url?user=xxx&password=xxx

7.2.3 编写SQL语句
  • 查询

    String sql = “select account,password from t_user”;

  • 添加

    String sql = “insert into t_user(account,password,nickname) values(?,?,?)”;

  • 删除

    String sql = “delete from t_user where id=?”;

  • 修改

    String sql = “update t_user set password=? where account=?”;

7.2.4 创建statement
  • 静态

    Statement statement = connection.createStatement();

  • 预编译

    PreparedStatement preparedStatement = connection.prepareStatement(sql);

7.2.5 发送sql语句并获取返回结果
  • executeUpdate

    非DQL 返回值类型 int

  • executeQuery

    DQL,返回值类型 ResultSet

7.2.6 查询结果集解析
  • 移动光标指向行数据

    next() while(next) if(next)

  • 获取列数据

    get类型(列的下表|列的名称)

    • 获取列的信息

      getMataData() ResultSetMataData对象包含列的信息

      getColumnCount() 获取列的数量

      getColumnLabel(下标) 获取列的名称
      verManager.getConnection();

  • 三个参数:DriverManager.getConnection(String url,String user,String password)

  • 两个参数:DriverManager.getConnection(String url,Properties info)

    info 有两个key : user 和 password

  • 一个参数:DriverManager.getConnection(String url)

​ url?user=xxx&password=xxx

7.2.3 编写SQL语句
  • 查询

    String sql = “select account,password from t_user”;

  • 添加

    String sql = “insert into t_user(account,password,nickname) values(?,?,?)”;

  • 删除

    String sql = “delete from t_user where id=?”;

  • 修改

    String sql = “update t_user set password=? where account=?”;

7.2.4 创建statement
  • 静态

    Statement statement = connection.createStatement();

  • 预编译

    PreparedStatement preparedStatement = connection.prepareStatement(sql);

7.2.5 发送sql语句并获取返回结果
  • executeUpdate

    非DQL 返回值类型 int

  • executeQuery

    DQL,返回值类型 ResultSet

7.2.6 查询结果集解析
  • 移动光标指向行数据

    next() while(next) if(next)

  • 获取列数据

    get类型(列的下表|列的名称)

    • 获取列的信息

      getMataData() ResultSetMataData对象包含列的信息

      getColumnCount() 获取列的数量

      getColumnLabel(下标) 获取列的名称

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值