Java JDBC

192 阅读4分钟

JDBC

JDBC简介

JDBC概念

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

Jdbc本质

官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口

各个数据库厂商去实现这套接口,提供数据库驱动jar包

我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类

JDBC好处

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

Snipaste_2022-11-23_14-10-19.png

JDBC快速入门

  1. 创建工程,导入驱动jar包
  2. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver")
  • MySQL 5之后的驱动包,可以省略注册驱动的步骤
  • 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
  1. 获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db1";
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
  1. 定义SQL语句
String sql = "update...";
  1. 获取执行SQL对象
Statement stmt = conn.createStatement();
  1. 执行SQL
int count = stmt.executeUpdate(sql);//返回受影响的行数
  1. 处理返回结果
System.out.println(count);
  1. 释放资源
stmt.close();
conn.close();

JDBC API

DriverManager

  • 驱动管理类

  • 作用

    • 注册驱动
    • 获取数据库连接
  • static void registerDriver(Driver driver)

    • 注册驱动
    • 在上面我们并没有使用使用这个静态方法来注册驱动,而是通过Class.forName("com.mysql.cj.jdbc.Driver")将这个Dreiver类加载进内存的
    • 看一下Driver类的源码
    //类中的静态代码块
    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    
    • 可以看到,随着类的加载,自动调用了DriverManager.registerDriver()这个方法
  • static Connection getConnection(String url, String user, String password)

    • 获取数据库连接

    • 参数

      • url:连接路径

        • 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
        • 示例:jdbc:mysql://127.0.0.1:3306/db1
        • 细节:
          • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为jdbc:mysql:///数据库名称?参数键值对1&参数键值对2...
          • 配置?useSSL=false参数,禁用安全连接方式,解决警告提示
      • user:用户名

      • password:密码

Connection

  • 数据库连接对象

  • 作用

    • 获取执行SQL对象
    • 管理事务
  • 获取执行SQL对象

    • 普通执行SQL对象
    Statement creatStatement()
    
    • 预编译SQL的执行SQL对象:防止SQL注入
    PreparedStatement prepareStatement(sql)
    
    • 执行存储过程的对象
    CallableStatement prepareCall(sql)
    
  • 事务管理

    • MySQL事务管理

      • 开启事务:BEGIN; / START TRANSACTION;
      • 提交事务:commit;
      • 回滚事务:ROLLBACK
      • MySQL默认自动提交事务
    • JDBC事务管理:Connection接口中定义了3个对应的方法

      • 开启事务:setAutoCommit(bollean autoCommit)

        • true:自动提交事务
        • false:手动提交事务,即为开启事务
      • 提交事务:commit()

      • 回滚事务:rollback()

    • 使用try..catch语句控制事务,同时执行完毕才算成功,否则回滚事务

    try {
        //开启事务
        conn.setAutoCommit(false);
        
        //执行sql
        int count1 = stmt.executeUpdate(sql1);
        //处理结果
        System.out.println(count1);
        //执行sql
        int count2 = stmt.executeUpdate(sql2);
        //处理结果
        System.out.println(count2);
        
        //提交事务
        conn.commit();
    } catch (Exception throwables) {
        //回滚事务
        conn.rollback();
        throwables.printStackTrace();
    }
    

Statement

  • 作用
    • 执行SQL语句
  • int executeUpdate(sql):执行DML、DDL语句
    • 返回值
      • DML语句影响的行数,通过返回值是否大于0来判断语句是否执行成功
      • DDL语句执行后,执行成功也可能返回0
  • ResultSet executeQuery(sql):执行DQL语句
    • 返回值:ResultSet结果集对象

ResultSet

  • 结果集对象

  • 作用

    • 封装了DQL查询语句的结果
  • ResultSet executeQuery(sql):执行DQL语句,返回ResultSet对象

  • 获取查询结果

    • boolean next()
      • 将光标从当前位置向前移动一行
      • 判断当前行是否为有效行
      • 返回值
        • true:有效行,当前行有数据
        • false:无效行,当前行没有数据
    • xxx getXxx(参数)
      • 获取数据
      • xxx:数据类型,如:int getInt(参数)String getString(参数)
      • 参数
        • int:列的编号,从1开始
        • String:列的名称
//循环判断游标是否是最后一行末尾
while(rs.nest()) {
    //获取数据
    rs.getXxx(参数);
}

PreparedStatement

  • 作用
    • 预编译SQL语句并执行:预防SQL注入问题
  • SQL注入
    • SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法

步骤

  • 获取PreparedStatement对象
//SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";

//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = comm.prepareStatement(sql);
  • 设置参数值
    • 给?赋值
    • 参数
      • 参数1:?的位置编号,从1开始
      • 参数2:?的值
PreparedStatement对象.setXxx(参数1, 参数2)
  • 执行SQL
    • 不需要再传递sql
executeUpdate();
//或
excuteQuery();
  • 好处
    • 预编译SQL,性能更高
    • 防止SQL注入:将敏感字符进行转义
  • PrepareStatement预编译功能开启:在url的后面加&useServerPreStmts=true
  • PrepareStatement原理
    • 在获取PrepareStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
    • 执行时就不用再进行这些操作了,速度更快
    • 如果sql模板一样,则只需要进行一次检查、编译