JDBC-基础篇(尚硅谷)

1. 引言

1.1 数据的存储

我们在开发java程序时,数据都是存储在内存中,属于临时存储,当程序停止或重启时,内存中的数据就丢失了!我们为了解决数据的长期存储问题,有如下方案:

  1. 数据通过I/O流技术,存储在本地磁盘中,解决了持久化问题,但是没有结构和逻辑,不方便管理和维护。

  2. 通过关系型数据库,将数据按照特定的形式交给数据库管理系统维护。关系型数据库是通过库和表分隔不同的数据,表中数据存储的方式是行和列,区分相同格式不同值的数据。

2. JDBC

2.1 JDBC的概念

  • JDBC:Java Database Connectivity,意为Java数据库连接

  • JDBC是java提供的一组独立于任何数据库管理系统的API

  • Java提供接口规范,由各个数据库厂商提供接口的实现,厂商提供的实现类封装成jar文件,也就是我们俗称的数据库驱动jar包

  • 学习JDBC,充分体现了面向接口编程的好处,程序只关心标准和规范,而无需关注实现过程

2.2 快速入门

package com.mdklea.base;
​
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
​
public class JDBCQuick {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
​
        //2. 获取连接对象
        String url = "jdbc:mysql://localhost:3306/atguigu";
        String username = "root";
        String password = "111111";
        Connection connection = DriverManager.getConnection(url, username, password);
        //3. 获取执行SQL语句的对象
        Statement statement = connection.createStatement();
​
        //4. 编写SQL语句,并执行,接受返回的结果集
        String sql = "SELECT emp_id,emp_name,emp_salary,emp_age FROM t_emp";
        ResultSet resultSet = statement.executeQuery(sql);
​
        //5. 处理结果,遍历resultSet结果集
        while (resultSet.next()) {
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
        }
​
        //6. 释放资源(先开后关原则)
        resultSet.close();
        statement.close();
        connection.close();
    }
}

3. 核心API理解

3.1 注册驱动

  • Class.forname("com.mysql.cj.jdbc.Driver");

  • 在java类中,当使用JDBC连接数据库时,需要加载数据库特定的驱动程序,以便于数据进行通信,加载驱动程序的目的是为了注册驱动程序,使得JDBC API能够识别并与特定的数据库进行交互

  • 从JDK6开始,不再需要显示地调用Class.forname() 来加载JDBC驱动程序,只要在类路径中继承了对应的jar文件,会自动在初始化时注册驱动程序。

3.2 Connection

  • Connection 接口是JDBC API的重要接口,用于建立与数据库的通信通道,换而言之,Connection对象不为空,则代表一次数据库连接。

  • 在建立连接时,需要制定数据库URL、用户名、密码参数。

    • URL:jdbc:mysql://localhost:3306/atguigu

      • jdbc:mysql://IP地址:端口号/数据库名称?参数键值对1&参数键值对2

  • Connection 接口还负责管理事务,Connection接口提供了commit和rollback方法,用于提交事务和回滚事务、

  • 可以创建Statement对象,用于执行SQL语句并于数据库进行交互。

  • 再使用JDBC技术时,必须要先获取Connection对象,在使用完毕后,要释放资源,避免资源占用浪费及泄露

3.3 Starement

  • Statement 接口用于执行SQL语句并与数据库进行交互,它是JDBC API 中的一个重要接口。通过Statement 对象,可以向数据库发送SQL语句并获取执行结果。

  • 结果可以是一个或多个结果。

    • 增删改:收影响行数单个结果。

    • 查询:单行单列、多行多列、单行多列等结果。

  • 但是Statement 接口在执行SQL语句时,会产生SQL注入攻击问题:

    • 当使用Statement 执行动态构建SQL查询时,往往需要将查询条件与SQL语句拼接到一起,直接将参数和SQL语句一并生成,让SQL的查询条件始终未true得到结果。

3.4 PreparedStatement

  • PreparedStatement 是 Statement 接口的子接口,用于执行 预编译 的SQL查询 作用如下:

    • 预编译SQL语句:在创建PreparedStatement时,就会预编译SQL语句,也就是SQL语句已经固定

    • 防止SQL注入:preparedStatement支持参数化查询,将数据作为参数传递到SQL语句中,采用?占位符的方式,将传入的参数用一对单引号包裹起来,无论传递什么都作为值。有效防止传入关键字或值导致SQL注入问题。

    • 性能提升:PreparedStatement是预编译SQL语句,同一SQL语句多次执行的情况下,可以复用,不必每次重新编译和解析。

  • 后续的学习我们是基于PreparedStatement进行实现,更安全,效率更高!

3.5 ResultSet

  • ResultSet是JDBC API 中的一个接口,用于表示从数据库中执行查询语句所返回的结果集,它提供了一种用于遍历和访问查询结果的方式。

  • 遍历结果:ReslutSet可以使用next() 方法将游标移动到结果集的下一行,逐行遍历数据库查询的结果,返回值为boolean类型,true代表由下一行结果,false则代表没有。

  • 获取单列结果:可以通过 getXxx的方法获取单列的数据,该方法为重载方法,支持索引和列名进行获取。

4. 基于PreparedStatement实现CRUD

4.1 查询单行单列

@SuppressWarnings({"all"})
    @Test
    public void testQuerySingleRowAndCol() throws SQLException {
        //1. 注册驱动 可以省略
        DriverManager.registerDriver(new Driver());
​
        //2. 获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "111111");
​
        //3. 获取SQL语句得到PreparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT COUNT(*) AS count FROM t_emp;");
​
        //4. 执行SQL语句,获取结果
        ResultSet resultSet = preparedStatement.executeQuery();
​
        //5. 处理结果(如果自己明确一定只有一个结果,那么resultSet最少要做一次next的判断,才能拿到我们要的列的结果)
        while (resultSet.next()) {
            int count = resultSet.getInt("count");
            System.out.println(count);
        }
        //6. 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

4.2 查询单行多列

@SuppressWarnings({"all"})
@Test
public void testQuerySingleRow() throws SQLException {
    //1. 注册驱动
    DriverManager.registerDriver(new Driver());
    //2. 获取连接
    Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "111111");
​
    //3. 获取SQL语句得到PreparedStatement对象
    PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM t_emp WHERE emp_id = ?");
​
    //4. 执行SQL语句,获取结果
    preparedStatement.setInt(1,3);
    ResultSet resultSet = preparedStatement.executeQuery();
    //5. 处理结果
    while (resultSet.next()) {
        int empId = resultSet.getInt("emp_id");
        String empName = resultSet.getString("emp_name");
        double empSalary = resultSet.getDouble("emp_salary");
        int empAge = resultSet.getInt("emp_age");
        System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
    }
    //6. 释放资源
    resultSet.close();
    preparedStatement.close();
    connection.close();
}

4.3 查询多行多列

@SuppressWarnings({"all"})
@Test
public void testQueryMoreRow() throws SQLException {
    //1. 注册驱动(可省略)
​
    //2. 获取连接
    Connection connection = DriverManager.getConnection
            ("jdbc:mysql:///atguigu","root","111111");
​
    //3. 获取SQL语句得到PreparedStatement 对象
    PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM t_emp WHERE emp_age > ?");
​
    //4. 执行SQL语句,获取结果
    preparedStatement.setInt(1,25);
    ResultSet resultSet = preparedStatement.executeQuery();
​
    //5. 处理结果
    while (resultSet.next()) {
        int empId = resultSet.getInt("emp_id");
        String empName = resultSet.getString("emp_name");
        double empSalary = resultSet.getDouble("emp_salary");
        int empAge = resultSet.getInt("emp_age");
        System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
    }
​
    //6. 释放资源
    resultSet.close();
    preparedStatement.close();
    connection.close();
}

4.4 插入数据

@SuppressWarnings({"all"})
@Test
public void testInsert() throws SQLException {
    //1. 注册驱动
​
    //2. 获取sql语句得到preparedStatement 对象
    Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu","root","111111");
​
    //3. 执行SQL语句,获取结果
    PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO t_emp (emp_name, emp_salary, emp_age) VALUES (?,?,?)");
​
    //4. 执行SQL语句,获取结果
    preparedStatement.setString(1,"MiloK");
    preparedStatement.setDouble(2,8888.8);
    preparedStatement.setInt(3,20);
    int result = preparedStatement.executeUpdate();
​
    if (result > 0 ) {
        System.out.println("成功");
    }else  {
        System.out.printf("失败");
    }
​
    //6. 释放资源
    preparedStatement.close();
    connection.close();
}

4.5 改变数据

@SuppressWarnings({"all"})
@Test
public void testUpdate() throws SQLException {
    Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu","root","111111");
​
    PreparedStatement preparedStatement = connection.prepareStatement("UPDATE t_emp SET emp_name = ? WHERE emp_id = ?");
​
    preparedStatement.setString(1,"mdk");
    preparedStatement.setInt(2,1);
    int result = preparedStatement.executeUpdate();
​
    if (result > 0) {
        System.out.println("成功");
    } else {
        System.out.println("失败");
    }
    preparedStatement.close();
    connection.close();
}

4.6 删除数据

@SuppressWarnings({"all"})
@Test
public void testDelete() throws SQLException {
    Connection connection = DriverManager.getConnection
            ("jdbc:mysql:///atguigu","root","111111");

    PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM t_emp WHERE emp_id = ?");
    
    preparedStatement.setInt(1,3);
    int result = preparedStatement.executeUpdate();

    if (result > 0) {
        System.out.println("成功");
    }else {
        System.out.println("失败");
    }
    preparedStatement.close();
    connection.close();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值