• JDBC 详解:原理介绍以及数据库操作


    目录

    一、引言

    二、JDBC 是什么

    1、我对 JDBC 的理解

    2、使用 JDBC 的好处

    3、JDBC 几个重要的类和接口介绍

    三、JDBC 操作数据库示例

    1、JDBC 编写步骤

    2、环境介绍

    3、下载驱动

    4、连接数据库

    5、注册用户

    6、登录用户

    7、修改用户

    8、注销用户

    四、总结 JDBC 的不足之处

    五、如何弥补 JDBC 的不足之处

    六、结语


    一、引言

    JDBC 很重要。它是一套标准规范,通过它可以访问不同的关系型数据库。它无处不在,存在于各种各样的 Java Web 项目中,用来连接数据库。它隐藏在持久层框架中,Mybatis 等持久层框架就是封装了 JDBC 操作数据库的过程。

    但是初学者在使用 JDBC 的过程中很容易出错,会遇到各种各样的问题。所以我觉得有必要专门写一篇文章介绍它的原理,并带着诸位一起操作数据库。如果这篇文章能够帮助你解决你遇到的问题和疑惑,那我觉得它的存在是有价值和意义的。如果你没使用 JDBC 成功的连接过数据库,我建议你跟着本教程一步一步的操作。只要你耐心学习,就能使用 JDBC 操作数据库,享受成功的喜悦。

    本文先会介绍 JDBC 的一些概念,再用一个常见的场景带着诸位使用 JDBC 连接 Mysql 数据库,进行增删改查。最后会总结一下 JDBC 的不足之处,以及如何弥补 JDBC 的不足之处。

    二、JDBC 是什么

    1、我对 JDBC 的理解

    JDBC 是一种规范,它在 Java 中定义了操作数据库的接口,这些接口包括连接数据库、操作数据库的增删改查、操作数据库的事务等等。至于,用什么通信协议连接数据库?怎样连接数据库?怎样操作数据库的增删改查?怎样操作数据库的事务?这些都由 Mysql 、Oracle 、SqlServer 等各大数据库厂商去实现,具体的实现细节肯定是不同的。

    所以这套规范保证了用一套 Java 代码就可以操作不同的数据库,为开发者屏蔽了一些细节问题.各大数据库厂商使用 Java 语言实现 JDBC 定义的接口后,会以 Jar 包供给开发者使用,这些 Jar 包就是数据库驱动,又叫数据库连接器。

    最常见的数据库连接器有 Mysql 连接器,经常看见的英文名是 mysql-connector-java。如果你不太了解它,推荐你看我之前写的一篇文章《mysql-connector-java详解》,或许你会有一定的收获。

    2、使用 JDBC 的好处

    Java 语言中定义了这一套 JDBC 的规范,使开发者使用 Java 语言操作数据库更加简单、方便。我总结了一下,有如下两点好处。

    1. 定义了操作数据库的标准类库,可以用同一种方式操作不同的数据库。
    2. 屏蔽了数据库驱动的底层实现,从而使开发者可以更简单的操作数据库。

    通过 JDBC 访问数据库的流程图如下:

    162d922d01a441de8ac44aeb45ef8435.png

    3、JDBC 几个重要的类和接口介绍

    • DriverManager :这个类管理一系列数据库驱动程序。匹配连接使用通信子协议从 JAVA 应用程序中请求合适的数据库驱动程序。识别 JDBC 下某个子协议的第一驱动程序将被用于建立数据库连接。
    • Driver :该接口提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
    • Connection :代表数据库的连接对象,此接口具有与数据库交互的所有方法,所有与数据库的通信仅通过这个连接对象进行。
    • Statement :通过调用 Connection 子类对象的 createStatement() 方法创建该接口的子类对象。将 Sql 语句提交到数据库执行,获取数据库执行的结果集。但是 Statement 有不足之处,比如:存在拼串操作,繁琐;存在 Sql 注入问题。
    • PrepatedStatement:该接口继承 Statement 接口,表示一条预编译过的 Sql 语句,可以使用该对象多次高效地执行 Sql 语句。它可以弥补 Statement 的不足之处,能预编译提高性能优化,能防止 Sql 注入。
    • CallableStatement:用于执行 SQL 存储过程

    三、JDBC 操作数据库示例

    接下来进入了实操的环节,我将使用 JDBC 操作 Mysql 数据库。相信我,只要你跟着我一步一步的操作,你也可以成功的使用 JDBC 操作数据库的。假设你开发了一个网站,用户可以在网站上进行注册(增)、登录(查)、修改用户名(改)、注销(删)等操作。这个场景模拟用户的一些操作,有些细节的地方简化了,可以不用去深究。

    1、JDBC 编写步骤

    我先说一下 JDBC 的编写步骤,如下 8 点所示:

    1. 加载数据库驱动
    2. 创建并获取数据库链接
    3. 创建 jdbc statement 对象
    4. 设置 sql 语句
    5. 设置 sql 语句中的参数(使用 preparedStatement )
    6. 通过 statemen t执行 sql 并获取结果
    7. 对 sql 执行结果进行解析处理
    8. 释放资源(resultSet、preparedstatement、connection)

    2、环境介绍

    下面介绍一下我编写和运行程序的环境和数据库的表结构。

    • JDK 版本:1.8及以上
    • Mysql 版本:8.0.25
    • Mysql 驱动版本:8.0.28

    我在 Mysql 中创建了一张用户表,用来演示数据库的增删改查,表结构如下所示:

    1. CREATE TABLE `user` (
    2. `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户id',
    3. `phone` char(11) NOT NULL COMMENT '手机号',
    4. `name` varchar(50) NOT NULL COMMENT '用户名',
    5. `pwd` varchar(50) NOT NULL COMMENT '密码',
    6. PRIMARY KEY (`id`)
    7. ) ENGINE=InnoDB COMMENT='用户表';

    3、下载驱动

    Mysql 驱动是 mysql-connector-java,下载驱动两种有方式。一种方式是到官网直接下载jar包,再将下载的 Jar 包放到项目的 lib 目录下,然后 build path。另一种方式是通过 Maven 下载,在 pom 文件中配置依赖。如果不知道怎么下载 Mysql 驱动,不太熟悉操作步骤,可以参考我之前写的文章《不同版本mysql-connector-java的jar包下载地址》

    我使用的是 Maven 依赖的方式,pom 文件的配置如下:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0</modelVersion>
    6. <groupId>com.test</groupId>
    7. <artifactId>jdbcTest</artifactId>
    8. <version>1.0-SNAPSHOT</version>
    9. <properties>
    10. <maven.compiler.source>8</maven.compiler.source>
    11. <maven.compiler.target>8</maven.compiler.target>
    12. </properties>
    13. <dependencies>
    14. <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    15. <dependency>
    16. <groupId>mysql</groupId>
    17. <artifactId>mysql-connector-java</artifactId>
    18. <version>8.0.28</version>
    19. </dependency>
    20. <dependency>
    21. <groupId>org.junit.jupiter</groupId>
    22. <artifactId>junit-jupiter</artifactId>
    23. <version>RELEASE</version>
    24. <scope>compile</scope>
    25. </dependency>
    26. </dependencies>
    27. </project>

    4、连接数据库

    先配置好数据库的 url 、用户名和密码,然后获取数据库连接,最后打印连接。我使用 Junit 测试,如果你不习惯用 Junit ,也可以使用 main 方法测试。

    1. import org.junit.jupiter.api.Test;
    2. import java.sql.Connection;
    3. import java.sql.Driver;
    4. import java.sql.SQLException;
    5. import java.util.Properties;
    6. public class ConnectionTest {
    7. @Test
    8. public void testConnection() throws SQLException {
    9. // 获取Driver实现类对象
    10. Driver driver = new com.mysql.jdbc.Driver();
    11. // url:jdbc:mysql://localhost:3306/test
    12. // jdbc:mysql:协议
    13. // localhost:ip地址
    14. // 3306:默认mysql的端口号
    15. // test:test数据库
    16. String url = "jdbc:mysql://localhost:3306/test";
    17. // 将用户名和密码封装在Properties中
    18. Properties info = new Properties();
    19. info.setProperty("user", "root");
    20. info.setProperty("password", "root");
    21. Connection conn = driver.connect(url, info);
    22. System.out.println(conn);
    23. }
    24. }

    程序运行的结果如下图所示,我用红框标识出了数据库连接。你测试一下,看一下你是否能打印出数据库连接。

    0520c5788a5b4555a6e6d98239761357.png

    5、注册用户

    通过 JDBC 成功的连接数据库,我们开始注册用户了,注册用户就是往数据库中插入一下用户数据。因为获取数据库连接和关闭数据库连接比较繁琐,我将这两个过程封装工具类 JDBCUtils 。

    1. package utils;
    2. import java.sql.*;
    3. /**
    4. * @Description 操作数据库的工具类
    5. */
    6. public class JDBCUtils {
    7. /**
    8. *
    9. * @Description 获取数据库的连接
    10. * @return
    11. * @throws Exception
    12. */
    13. public static Connection getConnection() throws Exception {
    14. // 1.配置基本信息
    15. String url = "jdbc:mysql://localhost:3306/test";
    16. String user = "root";
    17. String password = "xxx";
    18. String driverClass = "com.mysql.cj.jdbc.Driver";
    19. // 2.加载驱动
    20. Class.forName(driverClass);
    21. // 3.获取连接
    22. Connection conn = DriverManager.getConnection(url, user, password);
    23. return conn;
    24. }
    25. /**
    26. *
    27. * @Description 关闭连接和Statement的操作
    28. * @param conn
    29. * @param ps
    30. */
    31. public static void closeResource(Connection conn,Statement ps){
    32. try {
    33. if(ps != null)
    34. ps.close();
    35. } catch (SQLException e) {
    36. e.printStackTrace();
    37. }
    38. try {
    39. if(conn != null)
    40. conn.close();
    41. } catch (SQLException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. /**
    46. *
    47. * @Description 关闭资源操作
    48. * @param conn
    49. * @param ps
    50. * @param rs
    51. */
    52. public static void closeResource(Connection conn,Statement ps,ResultSet rs){
    53. try {
    54. if(ps != null)
    55. ps.close();
    56. } catch (SQLException e) {
    57. e.printStackTrace();
    58. }
    59. try {
    60. if(conn != null)
    61. conn.close();
    62. } catch (SQLException e) {
    63. e.printStackTrace();
    64. }
    65. try {
    66. if(rs != null)
    67. rs.close();
    68. } catch (SQLException e) {
    69. e.printStackTrace();
    70. }
    71. }
    72. }

     有了该工具类,接下来注册用户就简单了,代码如下所示:

    1. /**
    2. * 用户注册
    3. */
    4. @Test
    5. public void testAdd() {
    6. Connection conn = null;
    7. PreparedStatement ps = null;
    8. try {
    9. String sql = "INSERT INTO `test`.`user`( `phone`, `name`, `pwd`) VALUES ( ?, ?, ?)";
    10. conn = JDBCUtils.getConnection();
    11. ps = conn.prepareStatement(sql);
    12. //3.填充占位符
    13. ps.setInt(1, 1326666666);
    14. ps.setString(2, "zhangsan");
    15. ps.setString(3, "123456");
    16. int count = ps.executeUpdate();
    17. if (count > 0) {
    18. System.out.println("注册成功");
    19. } else {
    20. System.out.println("注册失败");
    21. }
    22. } catch (Exception e) {
    23. e.printStackTrace();
    24. } finally {
    25. JDBCUtils.closeResource(conn, ps);
    26. }
    27. }

    程序运行的结果如下图所示,打印出了注册成功,同时数据库中也有了一条记录。

    0eac594f8bc048ed890744e14269ffe8.png

    9b4b8731dc32456f8483b8215557a592.png

    6、登录用户

    登录用户就是用手机号码和密码做为条件,查询数据库中的用户表。如果查到了数据,就登录成功。如果没查到数据,就登录失败。

    1. /**
    2. * 用户登录
    3. */
    4. @Test
    5. public void testLogin() {
    6. Connection conn = null;
    7. PreparedStatement ps = null;
    8. ResultSet resultSet = null;
    9. try {
    10. conn = JDBCUtils.getConnection();
    11. String sql = "select * from user where phone = ? and pwd = ?";
    12. ps = conn.prepareStatement(sql);
    13. ps.setString(1, "1326666666");
    14. ps.setString(2, "123456");
    15. resultSet = ps.executeQuery();
    16. if (resultSet.next()) {
    17. System.out.println(resultSet.getString("name") + "登录成功");
    18. } else {
    19. System.out.println("用户名不存在或密码错误");
    20. }
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. } finally {
    24. JDBCUtils.closeResource(conn, ps, resultSet);
    25. }
    26. }

    结果如下图所示,登录成功。

    c4eba191b053428db442fc6ff22bdf97.png

    7、修改用户

    修改用户就是用登录查出的用户的id做为条件,更新用户名。在这里我将用户名【zhangsan】改为【zhangsan1】。

    1. /**
    2. * 修改用户名
    3. */
    4. @Test
    5. public void testUpdate() {
    6. Connection conn = null;
    7. PreparedStatement ps = null;
    8. try {
    9. String sql = "UPDATE `user` SET `name` = ? WHERE `id` = ?";
    10. conn = JDBCUtils.getConnection();
    11. ps = conn.prepareStatement(sql);
    12. //3.填充占位符
    13. ps.setString(1, "zhangsan1");
    14. ps.setInt(2, 1);
    15. int count = ps.executeUpdate();
    16. if (count > 0) {
    17. System.out.println("修改成功");
    18. } else {
    19. System.out.println("修改失败");
    20. }
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. } finally {
    24. JDBCUtils.closeResource(conn, ps);
    25. }
    26. }

    结果如下图所示,修改成功,并且数据库中的数据也改变了。

    e0c0540b45794e908f9d26902c1e949b.png

    31fbfa1cf30744e5a3bee2b0e1ad479e.png

    8、注销用户

    注销用户就是删除用户。

    1. /**
    2. * 注销用户
    3. */
    4. @Test
    5. public void testDelete() {
    6. Connection conn = null;
    7. PreparedStatement ps = null;
    8. try {
    9. String sql = "DELETE FROM `user` WHERE `id` = ?";
    10. conn = JDBCUtils.getConnection();
    11. ps = conn.prepareStatement(sql);
    12. //3.填充占位符
    13. ps.setInt(1, 1);
    14. int count = ps.executeUpdate();
    15. if (count > 0) {
    16. System.out.println("注销成功");
    17. } else {
    18. System.out.println("注销失败");
    19. }
    20. } catch (Exception e) {
    21. e.printStackTrace();
    22. } finally {
    23. JDBCUtils.closeResource(conn, ps);
    24. }
    25. }

    结果如下图所示,删除成功,并且数据库中的数据也删除了。

    88f5bef097f0499a83c740dbb362cd1c.png

    5e18dff932a248c7a1250874cdb545b9.png

    四、总结 JDBC 的不足之处

    现在,我们已经用 JDBC 将数据库的增删改查演示完了。通过上面的代码,我们也可以感受到 JDBC 的不足之处。那么,JDBC 有哪些不足?如下所示,总共有 4 点不足。

    1、在创建连接,关闭连接,异常处理的时侯有很多冗余、重复的代码,导致一个很长的方法中业务代码只占一小部分

    2、Sql 语句在代码中硬编码,不易维护

    3、Sql 输入参数需要自己映射,要手动处理sql中的占位符,将输入参数和占位符对应起来

    4、获取数据库返回的数据时,需要手动创建对象,再遍历结果集,将数据放到对象中

    五、如何弥补 JDBC 的不足之处

    既然知道了 JDBC 的不足之处,那就要弥补这些不足。所以一些持久层的框架就应运而生,这些持久层框架封装了 JDBC 操作数据库的过程,使开发者只需要关心 Sql 本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建 statement、手动设置参数、检索结果集等繁琐的过程。

    常见的持久层框架有 Mybatis 、 JdbcTemplate 、Hibernate 等。现在,大部分项目都会使用 Mybatis ,我也推荐使用你 Mybatis。JdbcTemplate 也可以使用,Hibernate 已经过时了,只有在一些老项目中才能看到它的身影。

    六、结语

    以上就是 JDBC 原理介绍以及数据库操作,诸位可以跟着步骤操作一下,不用担心连不上数据库了。我之前写过 Mysql 数据库驱动的文章,也写过持久层技术对比的文章。这一篇 JDBC 详解的文章是和那两篇文章相互呼应的,是同一个系列的文章。

    最后,做一个简单的调查,你有没有成功的使用 JDBC 操作过数据库?如果有,那恭喜你学会了使用 JDBC 编程。如果没有,那你可能遇到了问题,你可以将问题抛出来。基于这两种假设,你可以在评论区留言,大家一起讨论一下。

  • 相关阅读:
    【学习笔记30】JavaScript中数组的5种去重方法
    《推进农业水价综合改革的意见》解读
    到底什么是5G-R?
    巧妙利用表函数将MySQL数据导入到ClickHouse
    斩获 offer 的 Java 面试宝典
    js防抖、节流以及他们的应用场景
    Vue-3.5vuex分模块
    AMD 5600G + 华硕A520M 引起的 Windows与Linux双系统冲突问题
    KMP算法代码实现
    使用 OpenCV 测量物体尺寸
  • 原文地址:https://blog.csdn.net/keyboard_/article/details/127641832