超级详细的JDBC和数据库连接池讲解

时间:2024-04-14 09:00:16

文章目录

  • JDBC简介
    • 概念
    • 本质
    • 好处
  • JDBC快速入门
  • JDBC中API详解
    • DriverManager
      • 驱动管理类作用
      • 注册驱动
      • 获取连接
    • Connection
      • 数据库连接对象作用
      • 获取执行SQL的对象
      • 事务管理
    • Statement
      • 作用
      • 执行SQL语句
    • ResultSet
      • 原理
      • 使用步骤
    • PreparedStatement
      • SQL注入
      • 获取对象
      • 操作步骤
    • 原理
      • 好处
  • JDBC工具类
  • 三层开发业务的案例分析
    • 图解
    • 三层结构模型
    • 分层的好处
  • 数据库连接池
    • 简介
    • 实现
    • Druid连接池
      • 常用的配置参数
      • 基本使用
      • 使用步骤

JDBC简介

概念

就是使用Java语言操作关系型数据库的一套API
全称:Java DataBase Connectivity Java数据库连接

本质

是一套操作所有关系型数据库的规则,即接口
Snipaste_2024-04-13_18-22-29.png

好处

  1. 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  2. 可随时替换底层数据库,访问数据库的Java代码基本不变

JDBC快速入门

操作步骤

1. 创建工程,导入驱动jar包
在当前模块下创建lib文件夹,将jar包放到lib文件夹下,
2. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
3. 获取连接
Connection conn = DriverManager.getConnection(url,user,password);
4. 定义SQL语句
String sql = "select ...";
5. 获取执行SQL对象
Statement stmt = conn.createStatement();
6. 执行SQL
boolean result = stmt.executeQuery(sql);
7. 处理返回结果
System.out.println(result);
8. 释放资源
stmt.close();
conn.close();

JDBC中API详解

DriverManager

驱动管理类作用

  1. 注册驱动
  2. 获取数据库连接

注册驱动

Class.forName(“com.mysql.jdbc.Driver”);
Driver类源码
Snipaste_2024-04-13_18-50-23.png
此处也可写成DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 用前面代码创建Driver类,创建时静态代码块又会创建Driver类,使其创建了俩次,所有用最上面class那个代码

获取连接

static Connection getConnection(String url,String user,String password)

  1. url:连接路径

Snipaste_2024-04-13_18-57-50.png

  1. user:用户名
  2. password:密码

连接路径详解
Snipaste_2024-04-13_18-58-59.png

Connection

数据库连接对象作用

  1. 获取执行SQL的对象
  2. 管理事务

获取执行SQL的对象

  • 普通执行SQL对象

Statement createStatement()

  • 预编译SQL的执行SQL对象:防止SQL注入

PrepareStatement prepareStatement(sql)

事务管理

开启事务:SetAutoCommit(boolean autoCommit):
true为自动提交事务,false为手动提交事务(开启事务)
提交事务:commit()
回滚事务:rollback()

Statement

作用

执行SQL语句

执行SQL语句

  • int executeUpdate(sql):执行DML,DDL语句
    • 返回值:DDL执行成功返回0
    • DML语句影响的行数
  • ResultSet executeQuery(sql):执行DQL语句
    • 返回值:ResultSet结果集对象

ResultSet

原理

  1. ResultSet内部有一个指针,刚开始记录开始位置
  2. 调用next方法,ResultSet内部指针会移动到下一行数据,存在返回true,不存在返回false
  3. 我们可以通过ResultSet得到一行数据getXxx得到某列数据

Snipaste_2024-04-13_19-24-53.png

使用步骤

  1. 游标向下移动一行,并判断改行是否有数据:next()
  2. 获取数据:getXxx(参数)
while(rs.next()){
    re.getXxx(参数);
}

PreparedStatement

SQL注入

用户在页面提交数据的时候人为的添加一些特殊字符,使得sql语句的结构发生了变化,最终可以在没有用户名或者密码的情况下进行登录

获取对象

PreparedStatement是Statement的子接口,可以防止sql注入问题
PreparedStatement prepareStatement(String sql)
注意:sql提前创造好的,sql语句中需要参数,使用?占位
select * from user where username = ?and password = ?;

操作步骤

1.PreparedStatement pstmt = conn.prepareStatement(sql);

2.pstmt.setXxx(int index,要放入的值);
第一个参数:int index:表示sql语句中问号出现的位置,从1开始计数
第二个参数:给问号的位置传入的值

3.执行,不需要再传递sql了
pstmt.executeQuery();  执行select
pstmt.executeUpdate();  执行insert,update,delete

原理

  1. 在获取PreparedStatement对象时,将SQL语句发送给mysql服务器进行检查,编译
  2. 执行时就不用再进行这些步骤了,速度更快
  3. 如果sql模板一样,则只需进行一次检查,编译

Snipaste_2024-04-13_20-11-44.png

好处

  1. 预编译SQL,性能更高
  2. 防止SQL注入:将敏感字符进行转义

JDBC工具类

通过学习上述代码,我们发现在执行增删改查的时候,除了sql语句和执行sql语句的对象不同外,其他都相同,所以我们可以将其重复的抽成一个抽象类
下面是我所写的代码:

public class JdbcUtil {

    private static final String DRIVER = "com.mysql.jdbc.Driver";

    private static final String URL = "jdbc:mysql://127.0.0.1:3306/db1?useSSL=false";

    private static final String USER = "root";

    private static final String PASSWORD = "123456";

    //注册驱动,仅执行一次,所以可以放到static代码块中
    static {
        try {
            Class.forName(DRIVER);

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }

    public static void getClose(Connection conn, Statement stmt) {
        getClose(conn,stmt,null);
    }

    public static void getClose(Connection conn, Statement stmt, ResultSet rs) {

        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

public class Demo {

    @Test
    public void testUitl(){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            conn.setAutoCommit(false);
            String sql = "update user set password = ? where username = ?";

            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,"666");
            pstmt.setString(2,"wangwu");
            int count = pstmt.executeUpdate();
            if (count > 0){
                System.out.println("更改成功");
                conn.commit();
            }else {
                conn.rollback();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtil.getClose(conn,pstmt,rs);
        }
    }
}

三层开发业务的案例分析

图解

Snipaste_2024-04-13_21-11-45.png

三层结构模型

  1. web层:接收客户端发送的数据 -> 把接收的数据封装成对象 -> 调用service层方法(并传递对象) -> 根据service层方法执行结果,给客户反馈
  2. service层:处理业务逻辑(会调用dao层中的方法)
  3. dao层:和数据库交互(底层利用jdbc技术)

分层的好处

  1. 解耦:降低代码的依赖关系
  2. 可维护性:哪一层出现问题,直接维护哪一层
  3. 可扩展性:哪一层需要添加代码,直接添加即可
  4. 可重用性:一个方法可以被其他层重复调用

数据库连接池

简介

数据库连接池是个容器,负责分配,管理数据库连接(Connection),它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
好处

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏

实现

  • 标准接口:DataSource
    • 获取连接 Connection getConnection
  • 常见的数据库连接池
    • DBCP
    • C3P0
    • Druid
  • Druid

Snipaste_2024-04-13_21-45-04.png

Druid连接池

常用的配置参数

Snipaste_2024-04-13_21-46-05.png

基本使用

核心类:DruidDataSourceFactory
public static DataSource createDataSource(Properties p);
创建一个properties配置文件,然后书写数据库连接参数(参考配置参数)

使用步骤

  1. 导入jar包
  2. 定义配置参数,定义参数
  3. 加载配置文件(创建properties对象)
  4. 获取数据库连接池对象(使用核心类构建连接池)
  5. 获取连接
  6. 执行sql语句
  7. 关闭资源,归还连接