JDBC

引言

Java程序操作数据库

JDBC

  • 本质:
    • sun公司官方定义的一套操作所有关系型数据库的规范,即接口。
    • 各个数据库厂商去实现这套接口,提供数据库驱动jar包
    • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

例如:MySQL中的jar包依赖

入门程序

  • 需求:基于JDBC程序,执行update语句 (update user set age = 25 where id = 1)
  • 步骤:
    • 准备工作:创建一个maven项目,引入依赖;并准备数据库表user。
    • 代码实现:编写JDBC程序,操作数据库

1.创建项目,引入依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.33</version>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.9.3</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
    </dependency>
</dependencies>

2.准备数据库表user

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
create table user(
    id int unsigned primary key auto_increment comment 'ID,主键',
    username varchar(20) comment '用户名',
    password varchar(32) comment '密码',
    name varchar(10) comment '姓名',
    age tinyint unsigned comment '年龄'
) comment '用户表';

insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大乔', 22),
                                                         (2, 'xiaoqiao', '123456', '小乔', 18),
                                                         (3, 'diaochan', '123456', '貂蝉', 24),
                                                         (4, 'lvbu', '123456', '吕布', 28),
                                                         (5, 'zhaoyun', '12345678', '赵云', 27);

3.编写测试类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.itheima;

import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JdbcTest {
    /*
        JDBC入门程序
    */

    @Test
    public void testUpdate() throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取数据库连接
        String url = "jdbc:mysql://localhost:3306/web01";
        String username = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url,username,password);

        //3.获取SQL语句执行对象
        Statement statement = connection.createStatement();

        //4.执行SQL
        statement.executeUpdate("update user set age = 25 where id = 1");

        //5.释放资源
        statement.close();
        connection.close();
    }
}

注册驱动时:先双击shift,然后在搜索框输入Driver,记得点击右上角的include…,找到后按照以下操作就可以找到驱动的路径(复制粘贴即可)

获取数据库连接时url固定的格式为’‘jdbc:mysql://’’,后面加上指定的数据库ip地址端口号

4.查看结果:

更新前:

更新后:

执行DQL语句

  • 需求:基于JDBC执行如下select语句,将查询结果封装到User对象中
  • SQL:select * from user where username = ‘daqiao’ and password = ‘123456’
  • ResultSet(结果集对象):ResultSet rs = statement.executeQuery()
    • next():将光标从当前位置向前移动一行,并判断当前行是否为有效行,返回值为boolean。
      • true:有效行,当前行有数据(解析各个字段的值,调用result当中get方法)
      • false:无效行,当前行没有数据(代表数据已经解析完了)
    • getXxx(…):获取数据,可以根据列的编号获取,也可以根据列名获取(推荐)。
  • 结果解析步骤:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Test
public void testSelect() throws Exception {
    String url = "jdbc:mysql://localhost:3306/web01";
    String USER = "root";
    String PASSWORD = "123456";

    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null; //封装查询返回的结果

    try {
        //1.注册JDBC驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取数据库连接
        conn = DriverManager.getConnection(url, USER, PASSWORD);

        //3.执行查询
        String sql = "select id,username,password,name,age from user where username = ? and password = ?";  //预编译SQL(推荐)【 ?:占位符】
        stmt = conn.prepareStatement(sql);

        stmt.setString(1, "daqiao");
        stmt.setString(2, "123456");

	    //将结果集封装在ResultSet对象中
        rs = stmt.executeQuery();

        //4.处理结果
        while (rs.next()) {
            User user = new User(
            rs.getInt("id"),
            rs.getString("username"),
            rs.getString("password"),
            rs.getString("name"),
            rs.getInt("age")
            );
            System.out.println(user);//使用Lombok的 @Data 自动生成 toString() 方法
        }
    }catch (SQLException se){   //捕获SQLException异常
        //Handle errors for JDBC
        se.printStackTrace();
    }catch (Exception e){   //捕获Exception异常
        //Handle errors for Class.forName
        e.printStackTrace();
    }finally {
        //5.释放资源
        try{
            if(rs != null) rs.close();
            if(stmt != null) stmt.close();
            if(conn != null) conn.close();
        }catch (SQLException se){   //捕获SQLException异常
            se.printStackTrace();
        }
    }
}

小结:

JDBC程序执行

  • DML语句:int rowsAffected = statement.executeUpdate();
  • DQL语句:ResultSet rs = statement.executeQuery();

DQL语句执行完毕结果集ResultSet解析?

  • resultSet.next():光标往下一行
  • resultSet.getXxx():获取字段数据

预编译SQL

1.静态SQL(参数硬编码)

2.预编译SQL(参数动态传递)

  • 优势一:可以防止SQL注入,更安全

    SQL注入:通过控制输入来修改实现定义好的SQL语句,以达到执行代码对服务器进行攻击的方法

    典型案例:

    演示:

    1.静态SQL

    准备一个静态SQL文件,在其控制台输入java -jar sql_Injection_demo-0.0.1-SNAPSHOT.jar

    (这个文件和下面的那个文件都是事先准备的)

    接着在浏览器输入其端口号:localhost:xxxx

    在上述页面中输入账号密码后就会在控制台输出账号密码,将用户名密码直接写死在了SQL语句中

    此时在用户名随意书写:sjashakjf,然后在密码输入’or'1’ = ‘1

    此时在SQL语句中就会变成如下的代码

    1
    2
    
    select count(*) from emp where username = 'songjiang' and password = '123456'	--原本
    select count(*) from emp where username = 'sjashakjf' and password = ''or'1' = '1'
    

    ‘‘or'1’ = ‘1’因为1 = 1是恒等,所以该语句不会报错(改变了原有的SQL语句的含义),就会登录成功

    2.预编译SQL

    准备一个静态SQL文件,在其控制台输入java -jar sql_Injection_demo-0.0.1-SNAPSHOT.jar

    接着在浏览器输入其端口号:localhost:xxxx

    使用这种方法后,就会将第一个字符串替换第一个字符,第二个字符串替换第二个字符,此时就不会改变原有的SQL语句的含义

  • 优势二:性能更高

本站于2026年3月31日建立
使用 Hugo 构建
主题 StackJimmy 设计