JDBC 详解

首先是官方文档:

https://docs.oracle.com/javase/tutorial/jdbc/basics/index.html

我们日常提供给前端的接口中的数据都是从数据库拿的,那怎么在Java代码中对数据库做增删改查呢,那就要用到JDBC了。

JDBC简介

Java DataBase Connectivity 意思是 Java数据库连接。

因为市面上的数据库很多,比如常用的MySql,Oracle,SqlServer等等,每个数据库的连接和操作的指令的都不一样,而JDBC就提供了一个标准,为访问不同数据库提供了统一的接口。这样,我们就只需要针对JDBC的接口开发就行,不需要去关心不同数据库底层的操作逻辑,底层的操作逻辑由数据库厂商去实现。

简单来讲,JDBC就是用来通过java程序去操作数据库的。

JDBC的使用步骤

首先给出 MySql JDBC官方文档

步骤如下:

  1. 加载数据库驱动,这个驱动由数据库厂商提供
  2. 建立连接,获取Connection
  3. 通过Statement对象访问数据库,由Connection产生,执行SQL语句
  4. 如果需要返回值,创建ResultSet对象,保存Statement执行之后查询的结果
  5. 释放资源

下面我们来走一遍步骤,以MySql为例

首先我们需要先创建好数据库以及表,然后我们需要MySql厂商提供的驱动,获取驱动的方式有很多,详细请看

https://github.com/mysql/mysql-connector-j

这里我们就以Maven依赖的方式安装驱动了

在这里插入图片描述

如图所示,版本尽量跟你MySql的版本保持一致,MySql的版本在连接的时候就能看到,如图
在这里插入图片描述

先来看下事先准备好的数据库以及表结构
在这里插入图片描述

有一个名字为xeon的数据库,其中有一张user表

下面我们就对user表做一些操作

代码如下

public static void main(String[] args) {

        try {
            /*1.加载MySql驱动*/
            Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
            /*2建立连接*/
            String url = "jdbc:mysql://localhost:3306/xeon";
            String user = "root";
            String pwd = "19930904";
            /*获取连接*/
            Connection connection = DriverManager.getConnection(url, user, pwd);

            /*获取Statement对象*/
            Statement statement = connection.createStatement();

            /*Sql语句*/
            String insertSql = "insert into user(name, age, gender, height, weight) values ('喻志强',28,'男',170,130);";


//            String updateSql="update user set name='yzq' where id=1";
//            String deleteSql = "delete from user where id=1";
            /*增删改都用executeUpdate 返回受影响的行数*/
            int count = statement.executeUpdate(insertSql);
            System.out.println("受影响的行数:" + count);

            /*查询数据*/
            String querySql = "select * from user";
            /*查询用executeQuery 返回的是一个结果集*/
            ResultSet resultSet = statement.executeQuery(querySql);
            /*循环取数据*/
            while (resultSet.next()) {
                /*根据列名取出数据*/
                int id = resultSet.getInt("id");
                System.out.println("id:" + id);
                String name = resultSet.getString("name");
                System.out.println("name:" + name);
            }

            /*释放资源 实际开发中一般是在 finally中去释放资源*/
            connection.close();
            statement.close();
            resultSet.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }

    }

注释写的很清楚了,没啥好讲的。

PreparedStatement

PreparedStatement 是 Statement的子类,主要提供了SQL占位符的功能。

能方便我们拼接sql语句,减少出错,以及防止 sql注入 的问题。

这里我们新建一个account表,并存入一条数据:
在这里插入图片描述

具体使用代码如下:

     public static void main(String[] args) {
        try {
            /*1.加载MySql驱动*/
            Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
            /*2建立连接*/
            String url = "jdbc:mysql://localhost:3306/xeon";
            String user = "root";
            String pwd = "19930904";
            /*获取连接*/
            Connection connection = DriverManager.getConnection(url, user, pwd);
            /*占位符Sql  ?就占位符*/
            String sql = "select * from account where user_name=? and pwd=?";
            /*获取PreparedStatement*/
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            /*按照顺序给占位符赋值*/
            preparedStatement.setString(1, "yuzhiqiang");
            preparedStatement.setString(2, "123456");
            /*执行查询*/
            ResultSet resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                System.out.println("登陆成功");
            } else {
                System.out.println("登录失败");
            }


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

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            
        }
    }

以上就是JDBC的常用方法,可以看到,上面的重复代码有点多,比如建立连接,释放资源等,这些重复代码我们可以稍微封装一下。

示例代码如下:

package com.yzq.jdbc.JDBC.utils;
import java.sql.*;

/**
 * @author : yuzhiqiang (zhiqiang.yu.xeon@gmail.com)
 * @description: JDBC工具类(根据自己需求封装)
 * @date : 2021/4/3
 * @time : 17:56
 */
public class JDBCUtil {

    private static Connection connection;
    private static final String url = "jdbc:mysql://localhost:3306/xeon";
    private static final String user = "root";
    private static final String pwd = "你的数据库密码";

    static {
        /*驱动只需要加载一次即可*/
        try {
            Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取连接
     *
     * @return
     */
    public static Connection getConnection() {
        /*获取 Connection*/
        try {
            connection = DriverManager.getConnection(url, user, pwd);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return connection;

    }


    /**
     * 释放资源
     *
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {

        try {
            if (connection != null) {
                connection.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

那我们之前的代码就可以改成下面这样

    public static void main(String[] args) {
        try {
            /*获取连接*/
            Connection connection = JDBCUtil.getConnection();
            /*占位符Sql  ?就占位符*/
            String sql = "select * from account where user_name=? and pwd=?";
            /*获取PreparedStatement*/
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            /*按照顺序给占位符赋值*/
            preparedStatement.setString(1, "yuzhiqiang");
            preparedStatement.setString(2, "123456");
            /*执行查询*/
            ResultSet resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                System.out.println("登陆成功");
            } else {
                System.out.println("登录失败");
            }
            /*释放资源*/
            JDBCUtil.close(connection, preparedStatement, resultSet);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }

数据库连接池

实际开发过程中,我们最近常用的就是跟数据库建立连接,拿数据。按照之前的写法,每次操作都要重新生成Connection对象,操作完之后,再回收。这样的话,有一万次操作就会创建一万次,非常浪费资源。

看到 “池”这个字 基本上都跟 资源复用,减少资源开销 有一定的关系。
比如线程池、字符串常量池等。数据库连接池也是用来 减少资源创建,对资源进行复用。

原理就是预先创建好要用的连接对象,这次用完之后并不销毁,下次还能再用而且不需要重新创建。

一般“池” 都会配合队列来使用,当池中的资源都处于正在使用的状态时没有空闲资源,那么新的请求就会放到队列等待,当有空闲资源后再进行处理。

MySql官方给我们提供了连接池的使用方法,具体可以看官方文档

数据库连接池

使用的是 import javax.sql.DataSource; 这个类

目前市面上近期还在维护的比较流行的三方库应该就是阿里开源的 druid 了, 而且druid不仅仅提供了数据库连接池的功能,还有很多其他好用的功能。

至于到底怎么选,可以根据 各种数据库连接池对比 自行决定。
详细的使用方法直接看文档就行,下面我们来简单用一用。

首先是添加依赖,查看最新版本:
https://mvnrepository.com/artifact/com.alibaba/druid


        <!--阿里 druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.5</version>
        </dependency>

简单使用:

    public static void main(String[] args) {
        /*创建 DruidDataSource 对象*/
        DruidDataSource druidDataSource = new DruidDataSource();
        /*配置数据库相关信息*/
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/xeon?useUnicode=true&characterEncoding=UTF-8");
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("你的数据库密码");
        //配置
        druidDataSource.setInitialSize(5);  //初始连接数
        druidDataSource.setMaxActive(20);  //最大连接数
        druidDataSource.setMinIdle(10);  //最小闲置数
        druidDataSource.setMaxWait(6000);  //获取连接等待超时的时间
        druidDataSource.setMaxOpenPreparedStatements(10); //缓存PreparedStatement的最大数量
        try {
            DruidPooledConnection connection = druidDataSource.getConnection();
            String sql = "insert into account(user_name, pwd) values(?,?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, "喻志强");
            preparedStatement.setString(2, "19930904");
            int execute = preparedStatement.executeUpdate();
            /*这里的close 并不是真正的销毁  而是回收  具体可以去看下源码*/
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

详细的配置可以去看文档
https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE

学完Servlet,数据库,以及JDBC,我们就可以模拟实际项目开发走一遍完整的请求以及响应流程了。

下一篇我们来写个小demo

用 kotlin+Gradle 开发服务端,模拟接口请求的完整流程(包含Java示例)


如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页