Detailed explanation of jdbc basics (super detailed)

JDBC Overview

Because the language we use in development is Java language, we must use Java language to operate the data in the database.

JDBC (Java Database Connectivity) is a standard interface for Java language to access relational databases. It provides a set of classes and methods for accessing and manipulating databases.

全称 ( Java DataBase Connectivity ) Java 数据库连接

Insert image description here

同一套java代码无法操作不同关系型数据库,我们要做到的是同一套Java代码操作不同的关系型数据库,而sun公司就指定了一套标准接口(JDBC),JDBC中定义了所有操作关系型数据库的规则

JDBC essence

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

JDBC Benefits

java代码不需要针对不同的数据库开发不同的代码
可更换底层数据库,而java代码基本不变

java database operation process

Insert image description here

第一步:编写Java代码
第二步:Java代码将SQL发送到MySQL服务端
第三步:MySQL服务端接收到SQL语句并执行该SQL语句
第四步:将SQL语句执行的结果返回给J

jdbc basic operations

After creating the project, remember to import the driver jar package and place it in the lib directory

package com.lz.jdbc;

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

/**
 * JDBC快速入门
 */
public class JDBCDemo {
    
    

    public static void main(String[] args) throws Exception {
    
    
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "select *from tb_user where id=2 ";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        ResultSet resultSet = stmt.executeQuery(sql);
        //6. 处理结果
        System.out.println(resultSet);
        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

This is just a simple code. For the specific code operation implementation, you can watch the teaching video to make it easier to implement.

Detailed explanation of JDBC API

DriverManager (driver management class)

Function one

注册驱动  获取数据库连接

The registerDriver method is used to register the driver.
In the above case, we use it Class.forName("com.mysql.jdbc.Driver");to register the driver.
The reason is that the registerDriver() method of the DriverManager object has been executed in the static code block in the Driver class to register the driver. Then we only need to load the Driver. class, the static code block will be executed. And Class.forName(“com.mysql.jdbc.Driver”); can load the Driver class.

MySql5之后的驱动包可以省略注册驱动的步骤

Function 2

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

Connection (database connection object)

effect:

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

Function 1: Get the execution object

Ordinarily execute SQL object
Statement createStatement()

        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();

Execution SQL object of precompiled SQL: preventing SQL injection (key point)
PreparedStatement prepareStatement(sql)

Role 2 transaction management

Transaction management operations in MySQL
开启事务 : BEGIN; 或者 START TRANSACTION;
提交事务 : COMMIT;
回滚事务 : ROLLBACK;
JDBC transaction management method.
package com.itheima.jdbc;

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

/**
 * JDBC API 详解:Connection
 */
public class JDBCDemo3_Connection {
    
    

    public static void main(String[] args) throws Exception {
    
    
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql1 = "update account set money = 3000 where id = 1";
        String sql2 = "update account set money = 3000 where id = 2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        try {
    
    
            // 开启事务
            conn.setAutoCommit(false);
            //5. 执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            //6. 处理结果
            System.out.println(count1);
            int i = 3/0;//模仿程序出错后将会进入catch中执行回滚事务
            //5. 执行sql
            int count2 = stmt.executeUpdate(sql2);//受影响的行数
            //6. 处理结果
            System.out.println(count2);

            // 提交事务
            conn.commit();
        } catch (Exception throwables) {
    
    
            // 回滚事务
            conn.rollback();
            throwables.printStackTrace();
        }
        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

Statement

Statement对象的作用就是用来执行SQL语句。而针对不同类型的
SQL语句使用的方法也不一样。
type of data function effect
Int executeUpdate(String sql) Execute a non-query SQL statement (usually an INSERT, UPDATE, or DELETE statement) and return the number of affected rows.
ResultSet executeQuery(String sql) Execute the query SQL statement (usually the SELECT statement) and obtain the returned result set. It returns a ResultSet object through which the query results can be accessed and manipulated.

ResultSet (result set object)

ResultSet (result set object)

=封装了SQL查询语句的结果

That is the type returned by the executeQuery(String sql) function, if we need to get the data we want from the ResultSet object. The ResultSet object provides methods for manipulating query result data.

Methods for manipulating query result data

boolean next()
将光标从当前位置向下一行移动一行
判断当前行是否为有效行
方法返回值说明:
true : 有效行,当前行有数据
false : 无效行,当前行没有数据
xxx getXxx(参数):获取数据
xxx : 数据类型;如: int getInt(参数) ;String getString()
参数
int类型的参数:列的编号,从1开始
String类型的参数: 列的名称

Insert image description here

一开始光标指定于第一行前,如图表头行。
当我们调用了 next() 方法后,光标就下移到第一行数据,并且方法返回true,
此时就可以通过 getInt("id") 获取当前行id字段的值,
也可以通过 getString("name") 获取当前行name字段的值。
如果想获取下一行的数据,继续调用 next() 方法,以此类推

Code

/**
  * 执行DQL
  * @throws Exception
  */
@Test
public void testResultSet() throws  Exception {
    
    
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的
3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn =
DriverManager.getConnection(url, username,
password);
    //3. 定义sql
    String sql = "select * from account";
    //4. 获取statement对象
    Statement stmt = conn.createStatement();
    //5. 执行sql
    ResultSet rs = stmt.executeQuery(sql);
    //6. 处理结果, 遍历rs中的所有数据
    /* // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据 getXxx()
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);
            System.out.println(id);
            System.out.println(name);
            System.out.println(money);
            System.out.println("--------------");

        }*/
    // 6.1 光标向下移动一行,并且判断当前行是否有数据
    while (rs.next()){
    
    
        //6.2 获取数据 getXxx()
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");
        System.out.println(id);
        System.out.println(name);
        System.out.println(money);
        System.out.println("--------------");
   }
    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

PreparedStatement

effect

预编译SQL语句并执行:预防SQL注入问题

SQL injection

SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达
到执行代码对服务器进行攻击的方法。

There is no program to prevent SQL injection. When we enter the password as ' or '1' ='1, it will show that the password is correct.
Why is this? Let’s look at the sql statement after string splicing

select * from tb_user where username = 'sjdljfld'
and password = ''or '1' = '1

No matter whether username = 'sjdljfld' and password = '' are satisfied or not, the '1' = '1' after or is always satisfied. The final condition is established and you can log in normally.

PreparedStatement overview

effect

PreparedStatement作用:
预编译SQL语句并执行:预防SQL注入问题

Get PreparedStatement object

// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username =
? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt =
conn.prepareStatement(sql);

Set parameter value

上面的sql语句中参数使用 ? 进行占位,在之前之前肯定要设置
这些 ? 的值。
PreparedStatement对象:setXxx(参数1,参数2):给 ?
Xxx:数据类型 ; 如 setInt (参数1,参数2)
参数:
参数1: ?的位置编号,从1 开始
参数2: ?的值

Improved using PreparedStatement

@Test
public void testPreparedStatement() throws
Exception {
    
    
    //2. 获取连接:如果连接的是本机mysql并且端口是默认的
3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn =
DriverManager.getConnection(url, username,
password);
    // 接收用户输入 用户名和密码
    String name = "zhangsan";
    String pwd = "' or '1' = '1";
    // 定义sql
    String sql = "select * from tb_user where
username = ? and password = ?";
    // 获取pstmt对象
    PreparedStatement pstmt =
conn.prepareStatement(sql);
    // 设置?的值
    pstmt.setString(1,name);
    pstmt.setString(2,pwd);
    // 执行sql
    ResultSet rs = pstmt.executeQuery();
    // 判断登录是否成功
    if(rs.next()){
    
    
        System.out.println("登录成功~");
   }else{
    
    
        System.out.println("登录失败~");
   }
    //7. 释放资源
    rs.close();
    pstmt.close();
    conn.close();
}

At this time, there is no need to pass the SQL statement when calling executeUpdate(); or executeQuery(); because the SQL statement has been precompiled when obtaining the SQL statement execution object.

PreparedStatement Benefits

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

PreparedStatement principle

Insert image description here

Java代码操作数据库流程如图所示:
将sql语句发送到MySQL服务器端
MySQL服务端会对sql语句进行如下操作
检查SQL语句
select * from tb_user where username = 'sjdljfld'
and password = '\'or \'1\' = \'1'
检查SQL语句的语法是否正确。
编译SQL语句。将SQL语句编译成可执行的函数。
检查SQL和编译SQL花费的时间比执行SQL的时间还要长。如
果我们只是重新设置参数,那么检查SQL语句和编译SQL语
句将不需要重复执行。这样就提高了性能。
执行SQL语句

Skip the introduction of enabling precompilation function

This article summarizes the JavaWeb course from Shang Silicon Valley, and I recommend that everyone take a look.

Guess you like

Origin blog.csdn.net/weixin_64618264/article/details/132921977