jdbc的API详解

1、DriverManager

  • 注册驱动
    // 这个可以不用写,mysql驱动里面配置了
    // 会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
    Class.forName("com.mysql.cj.jdbc.Driver");
    

com.mysql.cj.jdbc.Driver这个类中,有个静态代码块,是用来注册驱动的,源码如下:

package com.mysql.cj.jdbc;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}
  • 获取数据库连接
    //String url = "jdbc:mysql://127.0.0.1:3306/db1";
    // 如果是本机的mysql并且端口是默认的3306,可以简化书写
    String url = "jdbc:mysql:///db1";
    String url = "jdbc:mysql:///db1";
    String username = "root";
    String password = "root1234";
    // 2. 获取连接
    Connection conn = DriverManager.getConnection(url, username, password);
    

2、Connection

数据库连接对象

  • 获取执行的sql对象
    • 获取普通执行sql对象
      Statement statement = conn.createStatement();
      
    • 获取预编译sql执行的sql对象:防止sql注入
      PreparedStatement prepareStatement = conn.prepareStatement(sql);
      
  • 管理事务
    • 开启事务
      // true:设置成自动提交事务
      // false:设置成手动提交事务
      // 开启事务
      setAutoCommit(false)
      
    • 提交事务
      commit()
    • 回滚事务
      rollback()

例子

  1. 模拟数据
    drop table if exists account;
    create table if not exists account
    (
        id    int primary key auto_increment,
        name  varchar(10),
        money double(10, 2)
    );
    insert into account(name, money)
    values ('张三', 1000),
           ('李四', 1000);
    
  2. java代码
    // 如果是本机的mysql并且端口是默认的3306,可以简化书写
    String url = "jdbc:mysql:///db1";
    String username = "root";
    String password = "root1234";
    
    // 1. 注册驱动
    // 这个可以不用写,mysql驱动里面配置了
    // 会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
    //            Class.forName(className);
    // 2. 获取连接
    Connection conn = DriverManager.getConnection(url, username, password);
    // 3. 定义sql语句
    String sql1 = "update account set money = 111 where id = 1";
    String sql2 = "update account set money = 111 where id = 2";
    // 4. 获取执行sql的对象 statement
    Statement statement = conn.createStatement();
    /**
     * ========事务管理=================
     */
    try {
        // 开启事务
        conn.setAutoCommit(false);
        // 5. 执行sql语句
        int count1 = statement.executeUpdate(sql1);
        System.out.println("count: " + count1);
        // 模拟失败
        int i = 1 / 0;
        int count2 = statement.executeUpdate(sql2);
        System.out.println("count: " + count2);
        // 提交事务
        conn.commit();
    } catch (Exception e) {
        // 回滚事务
        conn.rollback();
        e.printStackTrace();
    }
    
    // 6. 处理结果
    // 7. 释放资源
    statement.close();
    conn.close();
    

3、Statement

作用就是执行sql语句

  • int executeUpdate(String sql):执行DML、DDL语句
    • 返回值:DML语句返回的是影响的行数,DDL语句返回的是0
  • ResultSet executeQuery(String sql):执行DQL语句
    • 返回值:查询的结果集

例子

  • executeUpdate 执行DML语句

    @Test
    public void testDML() throws Exception {
        //String url = "jdbc:mysql://127.0.0.1:3306/db1";
        // 如果是本机的mysql并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1";
        String username = "root";
        String password = "root1234";
        String className = "com.mysql.cj.jdbc.Driver";
        // 1. 注册驱动
        // 这个可以不用写,mysql驱动里面配置了
        // 会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
        // Class.forName(className);
        // 2. 获取连接
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3. 定义sql语句
        String sql = "insert into account(name, money) values ('张三丰', '2000');";
        // 4. 获取执行sql的对象 statement
        Statement statement = conn.createStatement();
        // 5. 执行sql语句
        int count = statement.executeUpdate(sql);
        // 6. 处理结果 count 为 1
        System.out.println("count: " + count);
        // 7. 释放资源
        statement.close();
        conn.close();
    }
    
  • executeUpdate 执行DDL语句

    @Test
    public void testDDL() throws Exception {
        //String url = "jdbc:mysql://127.0.0.1:3306/db1";
        // 如果是本机的mysql并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1";
        String username = "root";
        String password = "root1234";
        String className = "com.mysql.cj.jdbc.Driver";
        // 1. 注册驱动
        // 这个可以不用写,mysql驱动里面配置了
        // 会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
        // Class.forName(className);
        // 2. 获取连接
        Connection conn = DriverManager.getConnection(url, username, password);
        // 3. 定义sql语句
        String sql = "create table if not exists tb_test_ddl\n" +
                "(\n" +
                "    id       int primary key auto_increment,\n" +
                "    username varchar(20) not null unique,\n" +
                "    password varchar(20) not null default 123456\n" +
                ");";
        // 4. 获取执行sql的对象 statement
        Statement statement = conn.createStatement();
        // 5. 执行sql语句
        int count = statement.executeUpdate(sql);
        // 6. 处理结果 count 为 0
        System.out.println("count: " + count);
        // 7. 释放资源
        statement.close();
        conn.close();
    }
    
  • executeQuery 执行DQL语句

这里使用的是sql注入的例子

模拟数据

create table if not exists tb_user
(
    id       int primary key auto_increment,
    username varchar(20),
    password varchar(20)
);

insert into tb_user(username, password)
VALUES ('zhangsan', '123'),
       ('lisi', '123');

java 代码

@Test
public void testSqlInject() throws Exception {
    String url = "jdbc:mysql:///db1";
    String username = "root";
    String password = "root1234";

    Connection conn = DriverManager.getConnection(url, username, password);

    String name = "asdafa";
    String pwd = "' or '1' = '1";

    // 3. 定义sql语句
    String sql = "select * from tb_user where username='" + name + "' and password='" + pwd + "'";
    // select * from tb_user where username='asdafa' and password='' or '1' = '1'
    // 上面的语句相当于 select * from tb_user
    System.out.println(sql);

    Statement statement = conn.createStatement();
    // 通过执行上面的sql语句,是查询所有的user数据
    ResultSet rs = statement.executeQuery(sql);
    if (rs.next()) {
        System.out.println("登陆成功");
    } else {
        System.out.println("登陆失败");
    }
    // 释放资源
    rs.close();
    statement.close();
    conn.close();
}

4、ResultSet

ResultSet 里面是封装了DQL查询语句的结果

  • boolean next()
    • 将光标向下移动一位,判断当前行是否有效
    • 返回值:
      • true:有效行,当前行有数据
      • false:无效行,当前行没有数据
  • xxx getXxx(param) 获取数据
    • xxx:数据类型
      • 例如 int getInt(param)String getString(param)
    • param:参数,有两种
      • columnIndex:列的序号,是从1开始
      • columnLabel:列的名称

例子

@Test
public void testResultSet() throws Exception {
    String url = "jdbc:mysql:///db1";
    String username = "root";
    String password = "root1234";

    Connection conn = DriverManager.getConnection(url, username, password);
    // 3. 定义sql语句
    String sql = "select * from account";

    Statement statement = conn.createStatement();

    ResultSet rs = statement.executeQuery(sql);

    while (rs.next()) {
//            根据列的序号获取
//            int id = rs.getInt(1);
//            String name = rs.getString(2);
//            double money = rs.getDouble(3);
//            根据列的名称获取
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");
        System.out.println(id + " , " + name + " , " + money);
    }
    // 释放资源
    rs.close();
    statement.close();
    conn.close();
}

5、PreparedStatement

预编译sql并执行sql语句

好处

  • 预编译sql,性能更高
  • 防止sql注入:将敏感字符进行了转义

原理

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

    // sql语句里面的参数值使用?占位符替代
    String sql = "select * from tb_user where username= ? and password = ?";
    // 通过Connection对象传入对应的sql语句获取
    PreparedStatement prepareStatement = conn.prepareStatement(sql);
    
  2. 设置参数值 setXxx(p1,p2):给sql语句中?赋值

    • Xxx数据类型,如setInt(p1,p2)、setString(p1,p2)
    • 参数
      • p1: ? 占位符的位置序号,从1开始
      • p2: ?的值
  3. 执行sql

    • executeQuery() / executeUpdate() 在这里就不需要传递sql语句了

例子

@Test
public void testPreparedStatement() throws Exception {
    //  useServerPrepStmts=true 开启预编译功能   
    String url = "jdbc:mysql:///db1?useServerPrepStmts=true";
    String username = "root";
    String password = "root1234";

    Connection conn = DriverManager.getConnection(url, username, password);

    String name = "zhangsan";
//        String pwd = "' or '1' = '1";
    String pwd = "123";

    // 定义sql语句
    String sql = "select * from tb_user where username= ? and password = ?";
    // 获取 PreparedStatement 对象
    PreparedStatement prepareStatement = conn.prepareStatement(sql);
    // 给 ?设置值
    prepareStatement.setString(1, name);
    prepareStatement.setString(2, pwd);
    // 执行sql
    ResultSet rs = prepareStatement.executeQuery();
    if (rs.next()) {
        System.out.println("登陆成功");
    } else {
        System.out.println("登陆失败");
    }
    // 再次设置数据,并执行,在这里,就不需要进行检查编译了,
    prepareStatement.setString(1, "aaa");
    prepareStatement.setString(2, "pwd");
    rs = prepareStatement.executeQuery();
    if (rs.next()) {
        System.out.println("登陆成功");
    } else {
        System.out.println("登陆失败");
    }

    rs.close();
    prepareStatement.close();
    conn.close();
}

这里用到了junit单元测试,需要在pom.xml中导入junit

<dependencies>
    <!-- mysql 驱动 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.33</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>

</dependencies>

参考文献

1. 黑马程序员JavaWeb基础教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ljp345775

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值