Featured image of post JDBC-入门到高级

JDBC-入门到高级

3958 字

JDBC-入门

一、JDBC搭建:

1.准备数据库

2.下载连接驱动jar包。

3.创建Java项目,在项目下创建lib文件夹内,将下载完成的jar包复制到文件夹里面。

4.选中lib文件夹右键–>Add as Library(添加为库),与项目集成。

5.编写代码

完整代码:

 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
package com.Chiba.base;

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

public class JDBCQuick {
    public static <connection> void main(String[] args) throws Exception {
//        1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
//        2.获取连接对象
        String url = "jdbc:mysql://localhost:3306/jdbcdemo";
        String username = "root";
        //password修改成自己设置的mysql密码
        String password = "password";
        Connection connection = DriverManager.getConnection(url, username, password);
//        3.获取执行sql语句的对象  -->把sql语句发送给mysql的对象
        Statement statement = connection.createStatement();

//        4.编写SQL语句,并执行,接受返回的结果集
        String sql = "select emp_id,emp_name,emp_salary,emp_age from t_emp;";
        ResultSet resultSet = statement.executeQuery(sql);

//        5.处理结果,遍历result结果集
        while (resultSet.next()) {
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
        }
//        6.释放资源(遵循先开后关原则)-->目前有connection、statement、resultSet三个资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

二、核心API理解

2.1注册驱动

  • 1
    
    Class forname("com.mysql.cj.jdbc.driver");
    

    注册驱动是为了和数据库通信,加载驱动程序的目的是为了注册驱动程序,使得JDBC API能够识别并且与特定的数据库进行交互。

  • 从JDK6开始就不需要写Class forname()来加载JDBC驱动程序,只要在类路径中集成了对应的jar文件,会自动在初始化时注册驱动程序。

2.2 Connection

  • Connection接口是JDBC API的重要接口,用于建立与数据库通信通道,只要Connection不为空,就代表一次与数据库连接。

  • 在建立连接时,需要指定数据库URL用户名密码

    • URL:jdbc:mysql://localhost:3306/jdbcdemo

      • jdbc:mysql//IP地址:端口号/数据库名称?参数键值对1&参数键值对2

        • jdbc:mysql://是固定的
        • localhost对应着IP地址,这里不是固定的,如果说是买了云服务,那么就要写云服务厂商的数据库IP地址
        • 3306对应的端口号,一般默认的是3306。
        • 斜线分割后对应的jdbcdemo对应的是数据库名称,就是当前要操作那个数据库
        • 如果还有参数要设置添加这时候就不要用/了,要用?隔开,然后写key=value

    注:如果你用的是自己的IP地址(localhost)和默认端口号(3306)那么这时候url就可以写:com:mysql:///jdbcdemo

  • Connection接口还负责管理事务,Connection接口提供了commitrollback方法,用于提交事务和回滚事务。

  • 可以创建Statement对象,用于执行SQL语句并与数据库进行交互。

  • 在用jdbc技术时,必须先获取connection对象(如果没有获取Connection对象后续的操作不复存在),Connection也代表的是一次链接,在使用完毕后,要释放资源,避免资源占用浪费和泄露。

2.3 Statement

  • Statement接口用于执行SQL语句并与数据库进行交互。它是JDBC API中的重要接口。通过Statement对象,可以向数据库发送SQL语句并获取执行结果

  • 结果可以是一个或多个结果。

    • 增删改:受影响行数单个数据。
    • 查询:单行单列、多行多列、单行多列等结果。
  • Statement接口在执行SQL语句时,会产生SQL注入攻击问题:

    • 当使用Statement执行动态构建的SQL查询时,往往需要将查询条件与SQL语句拼接在一起,直接将参数和SQL语句一并生成,让SQL的查询条件始终为true得到结果。

2.4PreparedStatement

  • PreparedStatementStatement接口的子接口,用于执行预编译的SQL查询,作用如下:
    • 预编译SQL语句:在创建PreparedStatement时,就会预编译SQL,也就是SQL语句已经固定。
    • 防止SQL注入:PreparedStatement支持参数化查询,将数据作为参数传递到SQL语句中,采用?占位符的方式,将传入的参数用一对单引号(’’)包裹起来,无论传递什么都作为值,有效防止传入关键字或值导致SQL注入问题
    • 性能提升:PreparedStatement是预编译SQL语句,同一SQL语句多次执行的情况下,可以复用,不必每次重新编译和解析。
 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
package com.Chiba.base;

import java.sql.*;
import java.util.Scanner;

public class JDBCPrepared {
    public static void main(String[] args) throws Exception {
        String url = "jdbc:mysql://localhost:3306/jdbcdemo";
        String username = "root";
        //password修改成自己设置mysql的密码
        String password = "password";
        //password修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
        PreparedStatement preparedstatement = connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?");
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入姓名");
        String name = sc.nextLine();
        preparedstatement.setString(1,name);
        ResultSet resultSet = preparedstatement.executeQuery();
        while (resultSet.next()) {
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
        }
        resultSet.close();
        preparedstatement.close();
        connection.close();
    }
}
1
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name=?

如果用sql注入的话就是输入:abc’ or ‘1’=‘1,这时候abc' or '1'='1就会代替问号并且加上两边加上单引号:

1
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name='abc' or '1'='1'

这是后看着虽然和用Statement时候注入的形式一样,但是PreparedStatement会在他们中间加上转义字符,使得他们变成普通的值:

1
select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_name='abc\' or \'1\'=\'1'

**总结:**在实际应用中,不要使用Statement类,因为它有sql注入的漏洞,反而我们要统一的使用Statement的子类PreparedStatement类,它不仅可以防止sql注入还可以提高性能,因为它是预编译的,可以复用不需要每次都编译。总而言之,使用``PreparedStatement`更安全、更高效。

2.5ResultSet

  • ResultSet是JDBC API中的一个接口,用于从数据库中执行查询语句所返回的结果集,它提供了一种用于遍历和访问查询结果的方式。
  • 遍历结果:ResultSet可以使用**next()**方法将游标移动到结果集的下一行,逐行遍历数据库查询的结果,返回值为boolean类型,true表示有下一行的结果,false表示没有。
  • 获取单列结果:可以通过getXxx的方法获取单列的数据,该方法为重载方法 ,支持索引和列名进行获取。

专业术语–ORM:

JDBC全流程:注册驱动—>获取连接—>预编译获取PreparedStatement对象—>编写并执行sql语句—>遍历结果集—>资源释放

案例—>CURD

查询–>单行单列:

 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
package com.Chiba.base;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class TestDemo {
    public static void main(String[] args) throws Exception {
//        1.驱动注册
        Class.forName("com.mysql.cj.jdbc.Driver");
//        2.获取连接--->passowrd修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
//        3.预编译PreparedStatement对象
        PreparedStatement preparStatement = connection.prepareStatement("select count(*) as count from t_emp");
//        4.获取返回值
        ResultSet resultSet = preparStatement.executeQuery();
//        5.遍历值
        while(resultSet.next()){
            int count=resultSet.getInt("count");
            System.out.println(count);
        }
        resultSet.close();
        preparStatement.close();
        connection.close();
    }
}

查询–>单行多列:

 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
package com.Chiba.base;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
    @Test
public void testQuerySingleRow() throws Exception {
    //注册驱动
    Class.forName("com.mysql.cj.jdbc.Driver");
    //获取连接(url、name、password)--->passowrd修改为mysql设置的密码
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo","root","password");
    //预编译获取preparedStatement对象
    PreparedStatement preparedStatement=connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_id=?");
    //给占位符赋值然后执行并获取结果集
    preparedStatement.setInt(1,4);
    ResultSet resultSet=preparedStatement.executeQuery();
    //结果集遍历
    while(resultSet.next()){
        int empId=resultSet.getInt("emp_id");
        String empName=resultSet.getString("emp_name");
        Double empSalary=resultSet.getdouble("emp_salary");
        int empAge=resultSet.getInt("emp_age");
        System.out.println(empId+"\t"+empName+"\t"+empSalary+"\t"+empAge);
    }
    //关闭资源
    resultSet.close();
    preparedStatement.close();
    connection.close();
 }
}

查询–>多行多列:

 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
package com.Chiba.base;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
    @Test
public void testQueryMoreRow() throws Exception {
//        1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
//        2.获取连接(url、name、password)--->passowrd修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
//        3.预编译获得preparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_age>?");
//       4.为占位符赋值才能执行sql
        preparedStatement.setInt(1, 25);
        ResultSet resultSet = preparedStatement.executeQuery();
//        5.遍历
        while (resultSet.next()) {
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            System.out.println(empId + "\t" + empName + "\t" + empSalary + "\t" + empAge);
        }
//        6.资源释放
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

增加数据:

 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
package com.Chiba.base;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
    @Test
    public void testInsert() throws Exception {
//        1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
//        2.获取连接(url、name、password)-->passowrd修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
//        3.预编译获取preparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp(emp_name,emp_salary,emp_age)values(?,?,?)");
        preparedStatement.setString(1, "Mike");
        preparedStatement.setDouble(2, 9999.99);
        preparedStatement.setInt(3, 25);
        int res = preparedStatement.executeUpdate();
//        根据受影响行数判断true或false;
        if (res > 0) {
            System.out.println("True");
        } else {
            System.out.println("False");
        }
        preparedStatement.close();
        connection.close();
    }
}

更改数据:

 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
package com.Chiba.base;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCOperation {
    @Test
     public void testUpdate() throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
         //passowrd修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbcdemo", "root", "password");
        PreparedStatement preparedStatement = connection.prepareStatement("  update t_emp set emp_salary=? where emp_id=?;");
        preparedStatement.setDouble(1, 10000);
        preparedStatement.setInt(2, 6);
        int res = preparedStatement.executeUpdate();
        if (res > 0) {
            System.out.println("True");
        } else {
            System.out.println("False");
        }
//        关闭资源
        preparedStatement.close();
        connection.close();
    }
}

删除数据:

 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
package com.Chiba.base;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCOperation { 
@Test
    public void testDelete() throws Exception {
//        注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
//        获取连接 --->passowrd修改为mysql设置的密码
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "password");
//        预编译获取preparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement("delete  from t_emp where emp_id=?");
//        给占位符赋值,执行sql语句获取结果集
        preparedStatement.setInt(1, 7);
        int result = preparedStatement.executeUpdate();
        if (result > 0) {
            System.out.println("True");
        } else {
            System.out.println("False");
        }
//        关闭资源
        preparedStatement.close();
        connection.close();
    }

}

在执行sql返回结果的时候:

如果是查询就用executeQuery()

如果是增删改就用executeUpdate()

本博客已稳定运行 0
发布了 9 篇文章 | 共 8.8K
Hugo 主题 Stack 由Jimmy设计
Chiba
...