JDBC连接数据库小白级教程

虽然MyBatis等ORM(Object-Relational Mapping)框架在Java开发中变得非常流行,并且简化了数据库操作的复杂性,但学习JDBC仍然具有一定的重要性:

  • 基础理解:学习JDBC可以帮助你深入理解数据库连接和操作的底层原理。了解JDBC可以让你更好地理解MyBatis等ORM框架是如何工作的,以及它们背后的实现机制。

  • 灵活性:在一些特定的场景下,可能需要直接使用JDBC来完成一些特定的数据库操作。比如,在一些性能要求极高的场景下,直接使用JDBC可能比使用ORM框架更加高效。

  • 问题排查:在开发过程中,可能会遇到一些与数据库操作相关的问题,此时对JDBC的理解会帮助你更好地进行问题排查和调试。

  • 与其他技术的集成:JDBC作为Java的标准数据库连接API,很多其他的数据库相关技术都是基于JDBC来实现的。比如,连接池技术、分布式事务处理等都与JDBC紧密相关,因此对JDBC的了解可以帮助你更好地与这些技术进行集成。

  • 面试准备:在一些面试中,面试官可能会问及JDBC相关的问题,对JDBC的了解可以帮助你更好地准备面试


JDBC,即Java Database Connectivity,java数据库连接。在开发中我们可能会使用到各种的数据库,每一种数据库都有着自己的一套“方法”。难道我们需要每使用到一种数据库就要学习掌握一种新的方法吗?这样的话学习成本也太高了。这时候我们java由于用户多,多到能够让java来制定“标准”,其他数据库厂商都来根据java的标准来对接自己的数据库,好比java来定义接口,各个数据库厂商来写接口一样。这样我们的java用户就可以学习java的标准来连接不用的数据库了。

1. 获取对应版本的jar包

那么想要使用JDBC就必须先安装对应数据库的驱动包,下面依旧是以MySQL为例。

我使用的MySQL版本是5.7

C:\Users\86134\Desktop>mysql --version
mysql  Ver 14.14 Distrib 5.7.27, for Win64 (x86_64)

所以我就可以去中央仓库:https://mvnrepository.com/,来搜索mysql:

点进去之后,下拉选取对应的版本,我这里选取的是5.1.x,和自己的服务器版本对应。点击版本号之后,会进去对应版本的页面,然年后点击jar标识就会自动下载:

2. 将jar包导入到项目中

创建好一个java项目后,新建一个文件夹LIB,将下载的jar包复制到LIB文件夹下,然后右键选择

随便给它取一个名字,不妨就叫mysql-jar,然后点击ok,此时idea就已经导入了jar包,可以解析出jar包中包含的内容了。

3. JDBC使用步骤

3.1 创建数据库连接Connection

Connection接口实现类由数据库提供,获取Connection对象通常有两种方式:

1. 通过DriverManager(驱动管理类)的静态方法获取:

// 加载JDBC驱动程序 
Class.forName("com.mysql.jdbc.Driver");

// 创建数据库连接 
Connection connection = DriverManager.getConnection(url);

2. 是通过DataSource(数据源)对象获取。实际应用中会使用DataSource对象。

 DataSource ds = new MysqlDataSource();
 ((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/test");
 ((MysqlDataSource) ds).setUser("root");
 ((MysqlDataSource) ds).setPassword("root");
 Connection connection = ds.getConnection();

 setUrl()方法中,传入的就是mysql的url,MySQL数据连接的URL参数格式如下:

jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值

 既然出现了两种不同的连接方式,那么就需要对比一下,他们的区别是什么?

1. DriverManager类来获取的Connection连接,是无法重复利用的,每次使用完以后释放资源 时,通过connection.close()都是关闭物理连接

2. DataSource提供连接池的支持。连接池在初始化时将创建一定数量的数据库连接,这些连接 是可以复用的,每次使用完数据库连接,释放资源调用connection.close()都是将 Conncetion连接对象回收

3.2 创建操作命令Statement

Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statement对象。

 实际开发中最常用的是PreparedStatement对象

PreparedStatement相对于Statement的优势:

  • 预编译

    • Statement对象在执行SQL语句之前不进行编译,每次执行SQL语句时都会将SQL语句发送给数据库进行解析和编译。而PreparedStatement对象在创建时就会预编译SQL语句,数据库会将编译后的执行计划缓存起来,以便重复使用。因此,使用PreparedStatement可以提高性能,特别是在多次执行相同的SQL语句时。
  • SQL注入

    • 使用Statement执行SQL语句时,如果SQL语句中包含用户输入的数据,存在SQL注入的风险。因为SQL语句是在执行时动态拼接的,恶意用户可以通过在输入中插入恶意代码来执行额外的SQL操作。而PreparedStatement通过参数化查询的方式,将SQL语句与用户输入的数据分开,避免了SQL注入的问题
  • 可读性和维护性

    • 使用PreparedStatement可以使代码更具可读性和维护性。由于SQL语句与参数分开,易于理解和修改。
  • 性能

    • 由于PreparedStatement在创建时进行了预编译,并且执行计划被缓存,因此在某些情况下可能比Statement执行速度更快。尤其是当需要多次执行相同的SQL语句时,PreparedStatement通常会更高效

使用案例:

Statement statement = connection.createStatement();
// 或者
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM mytable WHERE id = ?");

3.3 使用操作命令执行SQL

主要掌握两种执行SQL的方法:

  • executeQuery() 方法执行后返回单个结果集的,通常用于select语句
  • executeUpdate()方法返回值是一个整数,指示受影响的行数,通常用于update、insert、delete 语句

使用案例:

ResultSet resultSet = statement.executeQuery("SELECT * FROM mytable");
// 或者
preparedStatement.setInt(1,2);
ResultSet resultSet = preparedStatement.executeQuery();

3.4 处理结果集ResultSet

ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供了对这些行中数据的访问。 ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next() 方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

案例:

while (resultSet.next()) {
     int id = resultSet.getInt("id");
     String sn = resultSet.getString("sn");
     String name = resultSet.getString("name");
     int classesId = resultSet.getInt("classes_id");
     System.out.println(String.format("Student: id=%d, sn=%s, name=%s, classesId=%s", id, sn, name, classesId));
 }

3.5 释放资源

释放资源需要关闭结果集、命令、连接(关闭顺序和创建顺序相反,这里就没有go语言中的defer还用了哈哈哈哈)

try {
    // 关闭结果集
    if (resultSet != null) {
        resultSet.close();
    }
} catch (SQLException e) {
    // 处理关闭结果集时可能发生的异常
    e.printStackTrace();
}

try {
    // 关闭命令
    if (statement != null) {
        statement.close();
    }
    // 如果使用了 PreparedStatement,也要关闭它
    if (preparedStatement != null) {
        preparedStatement.close();
    }
} catch (SQLException e) {
    // 处理关闭命令时可能发生的异常
    e.printStackTrace();
}

try {
    // 关闭连接
    if (connection != null) {
        connection.close();
    }
} catch (SQLException e) {
    // 处理关闭连接时可能发生的异常
    e.printStackTrace();
}

4. 完整使用案例代码

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.*;

public class JDBCDemo1 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            // 1. 创建数据库连接Connection
            //connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/csdn", "root", "yourPassWord");
            // 也可以通过DataSource获取连接
            DataSource ds = new MysqlDataSource();
            ((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/csdn?characterEncoding=UTF-8&useSSL=false");
            ((MysqlDataSource) ds).setUser("root");
            ((MysqlDataSource) ds).setPassword("yourPassWord");
            connection = ds.getConnection();

            // 2. 创建操作命令Statement 获取全部学生的id和name
            statement = connection.createStatement();
            
            // 3. 使用操作命令来执行SQL
            String sqlQuery = "SELECT * FROM student";
            resultSet = statement.executeQuery(sqlQuery);
            
            // 4. 处理结果集ResultSet
            while (resultSet.next()) {
                // Process each row of the result set here
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                // Do something with the retrieved data
                System.out.println("ID: " + id + ", Name: " + name);
            }

            //2. 创建操作命令PreparedStatement  查询id == 1 的学生id和name
            PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM student WHERE id = ?");
            
            // 3. 使用操作命令来执行SQL preparedStatement.setInt(参数index,参数值)
            preparedStatement.setInt(1,1);
            ResultSet resultSet1 = preparedStatement.executeQuery();
            
            // 4. 处理结果集ResultSet
            while (resultSet1.next()) {
                // Process each row of the result set here
                int id = resultSet1.getInt("id");
                String name = resultSet1.getString("name");
                // Do something with the retrieved data
                System.out.println("ID: " + id + ", Name: " + name);
            }



        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 5. 释放资源
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

注意更换成你自己的数据库和自己的root账户的密码,创建一个student表里面包含id、name属性

执行结果:

5.重点总结

学习下面两个问题你能答得上来吗?

1. 数据库连接有哪些方式?分别有什么区别

2. 数据库Statement和PreparedStatement有什么区别?

答案见博文3.2&&3.2

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小小小关同学

你的支持就是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值