数据库造神计划第二十一天---JDBC编程

🔥个人主页: 寻星探路

🎬作者简介:Java研发方向学习者

📖个人专栏:、《

⭐️人生格言:没有人生来就会编程,但我生来倔强!!!



目录

一、什么是JABC

1、JDBC的应用场景

2、JDBC工作原理

二、为什么要使用JDBC

三、使用JDBC

1、创建Maven工程并配置国内镜像

1.1创建Maven工程

1.2配置国内镜像(阿里的)

2、获取MySQL驱动包

3、修改pom.xml⽂件

4、建立数据库连接

5、创建Statement

6、执行SQL语句

7、处理结果集

8、释放资源

四、JDBC常用接口和类

[1、DriverManager 和DataSource](#1、DriverManager 和DataSource)

[2、DriverManager 与DataSource的区别](#2、DriverManager 与DataSource的区别)

[3、Connection 数据库连接](#3、Connection 数据库连接)

4、Statement对象

4.1Statement

4.2SQL注入

4.3PreparedStatement

4.4CallableStatement

4.5executeQuery()

4.6executeUpdate()

5、ResultSet结果集

六、示例


一、什么是JABC

JDBC(Java Data Base Connectivity,Java数据库连接)是Java程序和数据库之间的桥梁,包含了⼀套Java定义的用于执行SQL语句的接口,使开发者能够编写数据库的程序。JDBC的主要作用是: 与数据库建立连接、发送SQL语句和处理数据库执行结果。

1、JDBC的应用场景

如果JAVA要访问不同的数据库,那么就需要根据数据库的协议进行代码的开发

为了解决不同数据的使用场景,JAVA中只定义了用于连接和操作数据的接口--JDBC

具体的实现由数据库厂商来完成

2、JDBC工作原理

JDBC工作原理简洁地概括为:加载驱动、建立连接、创建Statement、执行SQL、处理结果和关闭资源。

二、为什么要使用JDBC

• 首先回顾⼀下使用客户端操作数据库的过程,主要分为以下几步:

a. 连接到数据库服务

b. 发送SQL语句

c. 得到返回结果并显示

d. 关闭连接

对于JAVA程序员来说,只需要调用JDBC定义的方法就可完成数据库的具体操作

• 同样如果使用程序操作数据库也会经历以上几步,⼤家应该可以想到,为实现上述步骤,可以编写相应的代码实现数据库连接,发送SQL语句,处理结果并显示,最后关闭连接。

• 但是不同的数据库对于同⼀个操作不论是协议还是参数都各有不同,如果让程序员自己去实现,那就必须针对不同的数据库进行编码实现,这个工作量和维护成本显然太大。

• Java采取的做法是把以上操作步骤定义了相应的接口,具体的实现交给数据库厂商去做,Java程序员只需要按照需要调用接口中定义的方法即可,这样不论使用什么数据库,都对于Java程序没有任何影响,即便是换⼀个数据库,也只需要换⼀下相应厂商的实现依赖。

JDBC使用过程可以概括为:加载数据库厂商的驱动包、建立连接、创建Statement、执行SQL、 处理结果释放资源和关闭连接。

三、使用JDBC

1、创建Maven工程并配置国内镜像

1.1创建Maven工程

1.2配置国内镜像(阿里的)

拖动到idea里面,把<mirrors></mirrors>中的内容换成下面的内容,再CTRL+s(保存)

(默认的仓库在国外,我们下载会很慢,所以要换成国内的镜像)

html 复制代码
<mirror>
 <id>aliyunmaven</id>
 <mirrorOf>*</mirrorOf>
 <name>阿⾥云公共仓库</name>
 <url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
 <id>central</id>
 <mirrorOf>*</mirrorOf>
 <name>aliyun central</name>
 <url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
 <id>spring</id>
 <mirrorOf>*</mirrorOf>
 <name>aliyun spring</name>
 <url>https://maven.aliyun.com/repository/spring</url>
</mirror>

2、获取MySQL驱动包

在Maven仓库(mvnrepository.com)搜索MySQL,找到最新版的驱动包

一般8.0.33就可以

3、修改pom.xml⽂件

在⼯程中的pom.xml中的新建<dependencies></dependencies>标签中添加MySQL依赖(把上图最下面的代码复制粘贴到<dependencies></dependencies>中间)

加载成功后可以通过以下方式查看

4、建立数据库连接

使用驱动管理类 DriverManager 的静态方法获取数据库连接

java 复制代码
// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");

// 获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jobs_info_db?characterEncoding" +
    "=utf8&allowPublicKeyRetrieval=true&useSSL=false", 
    "root", 
    "123456");

通过数据源 DataSource 对象获取,推荐在实际开发中应用这种方式

java 复制代码
// 设置数据源的连接串、⽤⼾名和密码
MysqlDataSource mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/jobs_info_db?characterEncoding" +
    "=utf8&allowPublicKeyRetrieval=true&useSSL=false");
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("123456");
// 把mysqlDataSource 转换为JDBC的dataSource  
DataSource dataSource = mysqlDataSource;

MySQL数据库连接URL格式: jdbc:mysql:// 服务器地址 : 端⼝ / 数据库 ? 参数名 = 值 [& 参数名 = 值 ]...

5、创建Statement

Statement是用于执行静态SQL语句并返回执行结果的对象

java 复制代码
// 通过connection获取statement对象 
Statement statement = connection.createStatement();

6、执行SQL语句

执行select查询时返回的是⼀个结果集,用ResultSet接收

执行nsert,update,delete操作时,返回的是受影响的行数,用int类型接收

java 复制代码
// 执⾏select语句, 并接收结果集 
ResultSet resultSet = statement.executeQuery("select id, name, sno, age, gender, enroll_date, class_id from student");

// 执⾏insert, update, delete语句,并接收受影响的⾏数 
int row = statement.executeUpdate("update student set age = 20 where id = 2");

7、处理结果集

如果返回的是⼀个结果集,则需要遍历这个集合获取对应列的值,具体代码如下:

java 复制代码
// 遍历结果集获取数据
while (resultSet.next()) {
    // 编号 
    long id = resultSet.getLong("id");
    // 姓名 
    String name = resultSet.getString("name");
    // 学号 
    String sno = resultSet.getString("sno");
    // 年龄 
    int age = resultSet.getInt("age");
    // 性别 
    byte gender = resultSet.getByte("gender");
    // ⼊学时间
    Date enrollDate = resultSet.getDate("enroll_date");
    // 班级编号
    long classId = resultSet.getLong("class_id");
    // TODO: 使⽤获取到的值... 
}

8、释放资源

在整个数据库访问过程中创建的对象都需要释放,包括:ResultSet,Statement和Connection, 后创建的先释放

java 复制代码
// 释放结果集 
if (resultSet != null) {
    try {
        resultSet.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
// 释放statement 
if (statement != null) {
    try {
        statement.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
// 关闭连接 
if (connection != null) {
    try {
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

四、JDBC常用接口和类

1、DriverManager 和DataSource

DataSource驱动管理类,用于管理JDBC驱动程序,可以从驱动程序中获取数据库连接,始于 JDK1.1。

DataSource数据源是DriverManager的替代方案,始于JDK1.4,是获取数据库连接的首选方法, 推荐使用。

2、DriverManager 与DataSource的区别

DriverManager和DataSource都可以获取到数据库连接,但它们之间存着着⼀些区别,主要在于连接的管理方式和资源利用效率

连接管理方式不同:

DriverManager每次调用getConnection方法都会初始化⼀个新的连接,使用完成后会关闭真实连接,导致资源浪费

DataSource使用了连接池的技术,会在初始化时创建⼀定数量的数据库连接,这些连接可以重复使用,关闭时并不是真正关闭连接,而是将连接归还给连接池,以供后续使用,有效地提高资源利用率和和性能

3、Connection 数据库连接

数据库连接(会话)对象,在连接的上下文中执行SQL语句并返回结果

4、Statement对象

4.1Statement

用于执行静态SQL语句并返回执行结果,由于只能执行静态语句,所以这⾥会有⼀个问题,假设⼀个语句中需要动态的参数,如where子句中的条件,那么只能通过字符串拼接的方式组装完成的SQL语句,如:

java 复制代码
String sql = "select * from student where name = '" + name + "' and class_id = " + classId;

字符串拼接形式构造SQL语句时,如果不处理参数中的特殊字符就会造成SQL注入,这是⼀个非常严重的安全性问题。

4.2SQL注入

SQL注入即是指web应用程序对用户输⼊数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进⼀步得到相应的数据信息。

大家一定不要去做没有授权的安全测试

4.3PreparedStatement

预编译SQL语句对象,SQL语句被预编译并存储在PreparedStatement对象中,可以使用该对象多次执行SQL语句,同时可以解决SQL注入问题。

例:通过Connection对象获取到PreparedStatement对象,需要传入SQL模板,动态参数用占位符?表示

java 复制代码
// 获取了个处理SQL的PrepareStatement对象 
PreparedStatement preparedStatement = connection.prepareStatement("select id, name, sno, age, gender, enroll_date, class_id from student where name = ? and class_id = ?");

为动态参数设置真实值,下标从1开始

java 复制代码
// ⽤真实值去替换占位符 
preparedStatement.setString(1, "宋江");
preparedStatement.setLong(2, 2);

执行SQL语句

java 复制代码
// select 操作 
ResultSet resultSet = statement.executeQuery();

// insert, update, delete操作 
int result = statement.executeUpdate();

4.4CallableStatement

用于执行SQL存储过程的接口。这里不做讨论

4.5executeQuery()

执行结果返回的是⼀个结果集,通常用于select操作

4.6executeUpdate()

执行结果返回的是⼀个整形,通常用于insert,update,delete操作

5、ResultSet结果集

是⼀个查询结果集的数据表,通常由执行查询操作的语句生成。

ResultSet对象维护了⼀个指向当前数据行的游标,最初游标位于第一行之前,调用next方法将游标移动到下⼀行,当ResultSet中没有更多的数据行时返回false,所以可以在while循环中使用它来遍历结果集。

ResultSet接口提供了getter⽅法(getBoolean、getLong等),用于从当前行检索列值,可以使用列的索引号或列的名称来检索值。⼀般来说,使用列索引会更有效率,索引编号从1开始,按照从左到右的顺序读取。

六、示例

查询学生编号为1的学生基本信息

java 复制代码
package org.bitejiuyeke;
import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.*;
import java.text.MessageFormat;
 
public class Demo_DataSource {
    public static void main(String[] args) {
        // 定义数据源 
        DataSource dataSource = null;
        // 定义连接对象 
        Connection connection = null;
        // 定义预编译对象     
        PreparedStatement statement = null;
        // 定义结果集对象 
        ResultSet resultSet = null;

        // 设置数据源参数 
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/java01?characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("123456");
        // 转为JDBC数据源 
        dataSource = mysqlDataSource;

        // 获取连接
        try {
            connection = dataSource.getConnection();
            // 获取了个处理SQL的PrepareStatement对象 
            statement = connection.prepareStatement("select id, name, sno, age, gender, " +"enroll_date, class_id from student where id = ?");
            // ⽤真实值去替换占位符 
            statement.setLong(1, 1);

            resultSet = statement.executeQuery();
            // 处理结果集,由于查询的是⼀条记录,这⾥⽤if即可 
            if (resultSet.next()) {
                long id = resultSet.getLong("id");
                String name = resultSet.getString("name");
                String sno = resultSet.getString("sno");
                int age = resultSet.getInt("age");
                byte gender = resultSet.getByte("gender");
                Date enrollDate = resultSet.getDate("enroll_date");
                long classId = resultSet.getLong("class_id");
                // 打印结果 
                System.out.println(MessageFormat.format("{0}, {1}, {2}, {3}, {4}, {5}, {6}", id, name, sno, age, gender,enrollDate, classId));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 在finally中释放所有资源 
            // 关闭结果集 
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            // 关闭预编译对象 
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            // 关闭数据库连接 
            if (connection != null) {
                try {
                    connection.close();
                 } catch (SQLException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
 }
相关推荐
A-刘晨阳3 小时前
从MongoDB到金仓:一次电子证照系统的平滑国产化升级实践
数据库·mongodb
瓜瓜怪兽亚3 小时前
前端基础知识---10 Node.js(三)
数据结构·数据库·node.js
掘根5 小时前
【Qt】常用控件3——显示类控件
开发语言·数据库·qt
码码哈哈爱分享5 小时前
MariaDB 与 MySQL 区别
数据库·mysql·mariadb
爱敲代码的TOM5 小时前
深入MySQL底层1-存储引擎与索引
数据库·mysql
GUIQU.5 小时前
【QT】嵌入式开发:从零开始,让硬件“活”起来的魔法之旅
java·数据库·c++·qt
牛奶咖啡139 小时前
关系数据库MySQL的常用基础命令详解实战
数据库·mysql·本地远程连接到mysql·创建mysql用户和密码·修改mysql用户的密码·设置mysql密码的使用期限·设置和移除mysql用户的权限
ANYOLY10 小时前
Redis 面试宝典
数据库·redis·面试
鲲志说10 小时前
数据洪流时代,如何挑选一款面向未来的时序数据库?IoTDB 的答案
大数据·数据库·apache·时序数据库·iotdb