[Java] JDBC quick start and detailed explanation (MySQL version)

1. JDBC Overview

1.JDBCConcept: Full name Java DataBase Connectivity, that is, Java database connection is a set of APIs that use Java to operate relational databases.

Driver: SUN has specified a set of standard interfaces (JDBC). JDBC defines all the rules for operating relational databases, and the implementation classes of the interfaces are given by the respective database vendors. This set of implementation classes is called a driver. If you want to use the same set of Java code to operate different relational databases, you only need to load the driver corresponding to the database manufacturer.

Insert image description here

2.The essence of JDBC:

  • An officially defined set of rules for operating all relational databases, that is, the interface
  • Various database vendors implement this set of interfaces and provide database driver jar packages.
  • You can use this set of interfaces (JDBC) for programming. The actual code executed is the implementation class in the driver jar package.

3. Java database operation process:

  • Write Java code
  • Java code sends SQL to MySQL server
  • The MySQL server receives the SQL statement and executes the SQL statement
  • Return the results of SQL statement execution to Java code

Insert image description here

2. JDBC Quick Start

2.1 Download the driver jar package

1. First check the MySQL version installed locally. My MySQL version here is8.0.32

mysql -V

Insert image description here

2. According to your local MySQL version, go to the MySQL official website to download the corresponding version of the compressed packagezip

MySQL official website download address:https://dev.mysql.com/downloads/connector/j/

ClickArchives to enter the historical version

Insert image description here

After selecting the version and operating system, click Download to download the zip package

  • Version: Select the locally installed database version, here is8.0.32
  • Operating System: Select Platform Independent, independent of platform

Insert image description here

3. After unzipping the zip package, take out the jar package inside. You will get after unzipping it here.mysql-connector-j-8.0.32.jar

Insert image description here

2.2 Data preparation

Prepare a tableaccount and insert two pieces of data as follows:

-- 删除账户表
drop table if exists account;

-- 创建账户表
create table account
(
    id    int primary key AUTO_INCREMENT comment 'ID',
    name  varchar(10) comment '姓名',
    money double(10, 2) comment '余额'
) comment '账户表';

-- 向账户表插入数据
insert into account(name, money) VALUES ('张三', 2000), ('李四', 2000);

-- 查询账户表
select * from account;

Insert image description here

2.3 Create project

1. Create a new project, define the name of the project, and specify the location.

Insert image description here

2. The generated project structure is as follows. First delete the src folderMain.java, and then create a new directory under the project, usually named < /span> packages. lib, used to store jar

Drag the downloaded mysql-connector-j-8.0.32.jar to the lib directory. The final project structure is as follows:

Insert image description here

3. Right-click the lib directory, click Add as Library, and add the jar package as a library file

Insert image description here

When adding as a library file, there are three options:

  • Global Library: Valid globally
  • Project Library: The project is valid
  • Module Library: The module is valid

Insert image description here

4. Create a new file in the src folder and name it herejavaJDBCDemo

Insert image description here

2.4 Writing code

Writing code is divided into the following seven steps:

  1. Register driver
  2. Get connection
  3. Define SQL statement
  4. Get execution SQL object
  5. Execute SQL
  6. Process the returned results
  7. Release resources

Copy the following code into JDBCDemo.java and run:

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

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/itheima"; // 数据库URL
        String username = "root"; // 用户名
        String password = "123456"; // 密码
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "update account set money = 3000 where id = 1";

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

        // 5.执行sql
        int count = stmt.executeUpdate(sql); // 受影响的行数

        // 6.处理结果
        System.out.println(count);
        
        // 7.释放资源
        stmt.close();
        conn.close();
    }
}

After the operation is completed, query the account table and find that Zhang San’s balance becomes 3000, indicating that the JDBC operation was successful. Here:

Insert image description here

3. Detailed explanation of JDBC API

3.1 DriverManager

The role of DriverManager (driver management class):

  • Register driver
  • Get database connection

1. Register driver: The registerDriver​(Driver driver) method is used to register the driver

The Driver class provided by MySQL implements the source code for registering the driver as follows:

Insert image description here

The DriverManager object's registerDriver() method has been executed in the static code block in this class to register the driver, then we only need to load < /span> class. method can load the Driver class, the static code block will be executed. The Class.forName()Driver

Class.forName("com.mysql.jdbc.Driver"); // 注册驱动

Note: For driver packages after MySQL 5, you can omit the step of registering the driver, and the driver class in the META-INF/services/java.sql.Driver file in the jar package will be automatically loaded.

2. Obtain database connection:getConnection()Method

getConnection​(String url, String user, String password);

Parameter Description:

  • url: database connection path
    • grammar:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
    • Example:jdbc:mysql://127.0.0.1:3306/itheima
  • user: username
  • poassword: password

Note:
1. If you are connecting to the local mysql server and the default port of the mysql service is 3306, the url can be abbreviated as: jdbc:mysql:///database name ?Parameter key-value pair
2. Configure the useSSL=false parameter in the url and disable the secure connection method to solve the warning prompt

3.2 Connection

The role of Connection (database connection object):

  • Get the object that executes SQL
  • management affairs

3.2.1 Obtain execution SQL object

1. Ordinary execution of SQL objects

Statement createStatement()

2. Precompile SQL execution SQL object: prevent SQL injection

PreparedStatement  prepareStatement(sql)

3. Object that executes stored procedures

CallableStatement prepareCall(sql)

3.2.2 Management matters

Operation commands for MySQL transaction management:

  • Open transaction: BEGIN or START TRANSACTION
  • Commit transaction:COMMIT
  • Rollback transaction:ROLLBACK

Note: MySQL automatically commits transactions by default

Three corresponding methods are defined in the Connection interface:

1. Open the transaction: setAutoCommit​(boolean autoCommit)
The parameter autoCommit indicates whether to automatically submit the transaction, true indicates automatic submission of the transaction, and false indicates manual submission of the transaction. To start a transaction, you need to set this parameter to false.

2. Submit the transaction:commit()

3. Rollback transaction:rollback()

The code is implemented as follows:

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

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/itheima?useSSL=false";
        String username = "root";
        String password = "123456";
        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; // 构造程序异常,如需正常运行,注释该行即可

            //5. 执行sql
            int count2 = stmt.executeUpdate(sql2);//受影响的行数
            //6. 处理结果
            System.out.println(count2);

            // ============提交事务==========
            //程序运行到此处,说明没有出现任何问题,则需提交事务
            conn.commit();
        } catch (Exception e) {
    
    
            // ============回滚事务==========
            //程序在出现异常时会执行到这个地方,此时就需要回滚事务
            conn.rollback();
            e.printStackTrace();
        }

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3.3 Statement

The purpose of the Statement object is to execute SQL statements. Different types of SQL statements use different methods.

Methods are classified as follows:

  • executeUpdate​(String sql): Execute DDL and DML statements and return the number of affected rows or no content.
  • executeQuery​(String sql): Execute DQL statement and return a single ResultSet object.

Note: The DQL statement involves the ResultSet object, which will be discussed in the 3.4 section

3.3.1 Execute DML statements

Execute DML statement: UseexecuteUpdate​(String sql) method to execute DML statement and return the number of affected rows

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 1.注册驱动,mysql8的驱动会自动加载注册,此行可以注释掉
        // Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "update account set money = 3000 where id = 1";

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

        // 5.执行sql
        int count = stmt.executeUpdate(sql); // 执行完DML语句,受影响的行数

        // 6.处理结果
        if(count > 0){
    
    
            System.out.println("修改成功~");
        }else{
    
    
            System.out.println("修改失败~");
        }

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3.3.2 Execute DDL statements

Execute DDL statement: UseexecuteUpdate​(String sql) method to execute DDL statement without returning content

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 1.注册驱动,mysql8的驱动会自动加载注册,此行可以注释掉
        // Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "alter table account add remark varchar(20)"; // 添加字段remark

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

        // 5.执行sql
        int count = stmt.executeUpdate(sql); // 执行完DDL语句,可能是0

        // 6.处理结果
        System.out.println(count);

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3.4 ResultSet

The role of ResultSet (result set object): encapsulates the results of SQL query statements, ResultSet executeQuery(sql) executes DQL statements and returns ResultSet objects.

3.4.1 ResultSet object methods

ResultSetThe object provides methods for manipulating query result data:

1.boolean next()

  • Move the cursor forward one line from the current position
  • Determine whether the current line is a valid line
    • Returning true indicates that the row is valid, that is, the current row has data
    • Returning false indicates that the row is invalid, that is, there is no data in the current row

2.xxx getXxx(参数): Get the data of this field, such as String getString​(String columnLabel), String getString​(int columnIndex)

  • xxx: represents the data type
  • 参数
    • Parameter of type int: column number, starting from 1
    • Parameters of type String: name of column

Note: Please note here that the column numbers start from 1, not 0

Example: Initially, the cursor is designated in front of the first row, that is, pointing to the header row. After the next() method is called, the cursor moves down to the first row of data, and The method returns true.
At this time, you can get the value of the id field of the current row through getInt("id"), or you can get the value of the name field of the current row through getString("name") .
If you want to get the data of the next row, you need to continue calling the next() method, and so on.

Insert image description here

3.4.2 Execute DQL statement

Execute DQL statement: UseexecuteQuery​(String sql) method to execute DQL statement and return the result set

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 1.注册驱动,mysql8的驱动会自动加载注册,此行可以注释掉
        // Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "select * from account";

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

        // 5.执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 6.处理结果,遍历rs中的所有数据
        // 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
    
    
            // 获取数据  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();
    }
}

The running results are as follows:

Insert image description here

Compare the query statements in the database as follows:

Insert image description here

Note: The method of obtaining data can also be replaced by the following

// 使用参数为列的名称
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");

// 使用参数为列的编号
int id = rs.getInt(1);
String name = rs.getString(2);
double money = rs.getDouble(3);

3.4.3 Encapsulating entity classes

Requirement: Query the account table data, encapsulate it as an Account object, and store it in the ArrayList collection.

Insert image description here

1. CreateAccountentity class corresponding toaccountaccount table data

public class Account {
    
    

    private Integer id; // ID
    private String name; // 姓名
    private Double money; // 余额

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Double getMoney() {
    
    
        return money;
    }

    public void setMoney(Double money) {
    
    
        this.money = money;
    }

    @Override
    public String toString() {
    
    
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

2. Execute the query statement

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * 查询account账户表数据,封装到Account对象中,并且存储到ArrayList集合中
 * 1. 定义实体类Account
 * 2. 查询数据,封装到Account对象中
 * 3. 将Account对象存入ArrayList集合中
 */
public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 1.注册驱动,mysql8的驱动会自动加载注册,此行可以注释掉
        // Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "select * from account";

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

        // 5.执行sql
        ResultSet rs = stmt.executeQuery(sql);

        List<Account> accountList = new ArrayList<>(); // 创建集合

        // 6.处理结果,遍历rs中的所有数据
        while (rs.next()){
    
    
            Account account = new Account(); // 创建account对象

            // 获取数据
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            //给account对象赋值
            account.setId(id);
            account.setName(name);
            account.setMoney(money);
            
            accountList.add(account); // 存入集合
        }

        System.out.println(accountList);

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

operation result:

[Account{id=1, name='张三', money=3000.0}, Account{id=2, name='李四', money=2000.0}]

3.5 PreparedStatement

The role of PreparedStatement: precompile SQL statements and execute them (to prevent SQL injection problems)

3.5.1 Demonstrate SQL injection

SQL injection: A method of modifying pre-defined SQL statements by manipulating input to execute code and attack the server.

The preparation materials are as follows: Baidu network disk link:https://pan.baidu.com/s/1vzYHt1y4fEvcnyTyiRRDDw, extraction code: d1wy

  • sql.jar
  • application.properties

Insert image description here

1. Modifyapplication.properties the file and modify the configuration to your local database user name and password

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/itheima?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456

2. Open the terminal and enter the command to run the program

java -jar sql.jar

Note: application.properties and sql.jar must be placed in the same directory, otherwise an error will be reported

Insert image description here

3. After running, the database will be automatically createdtest and the tableuser will be created

Insert image description here

userThe contents of the table are as follows: store username and password information

Insert image description here

4. Enter http://localhost:8080/login.html in the browser to enter the login page. First test whether the login page is valid.

Enter the correct username and password: zhangsan and 123

Insert image description here

Insert image description here

Entering incorrect username and password:

  • zhangsanand1234
  • abcand123

Insert image description here

Insert image description here

5. To demonstrate SQL injection, enter any user name when logging in, but enter a specific string for the password, and find that you can log in successfully.

Enter the username and password as follows: abc and ' or '1' ='1

Insert image description here

3.5.2 Analyzing SQL Injection

The code simulates the process of SQL injection:

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 接收用户输入的用户名和密码,然后拼接成sql
        /*String name = "zhangsan";
        String pwd = "123";*/
        String name = "abc";
        String pwd = "' or '1' = '1";
        String sql = "select * from user where username = '"+name+"' and password = '"+pwd+"'";
        System.out.println(sql); // select * from user where username = 'abc' and password = '' or '1' = '1'

        // 获取Statement对象
        Statement stmt = conn.createStatement();

        // 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 判断登录是否成功
        if(rs.next()){
    
    
            System.out.println("登录成功~");
        }else{
    
    
            System.out.println("登录失败~");
        }

        // 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

The above code splices the username and password into a sql statement. The spliced ​​sql statement is as follows:

select * from user where username = 'abc' and password = '' or '1' = '1'

It can be seen from the above statement that the condition username = 'abc' and password = '' is satisfied or not, and the following after or is always satisfied. , the final condition is established, and you can log in normally. '1' = '1'

3.5.3 Solve SQL injection

PreparedStatement: Using the PreparedStatement object can prevent SQL injection problems.

PreparedStatementObject usage:

1. Get the PreparedStatement object

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

// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);

2. Set the parameter value, that is, the value of ?

The parameters in the above sql statement use ? as placeholders. You must set these ? values ​​before executing the sql.

PreparedStatementThe object provides methods for setting parameter values: setXxx(参数1,参数2), such as setString​(int parameterIndex, String x)

  • Xxx: indicates data type
  • parameter:
    • Parameter 1: The position number of ?, starting from 1
    • Parameter 2: The value of ?

3. Execute SQL statements

  • executeUpdate(): Execute DDL statements and DML statements
  • executeQuery(): Execute DQL statement

Note: There is no need to pass the SQL statement when calling these two methods, because the SQL statement has been precompiled when obtaining the SQL statement execution object.

UsePreparedStatementModification:

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 接收用户输入的用户名和密码
        String name = "zhangsan";
        // String pwd = "123";
        String pwd = "' or '1' = '1";

        // 定义sql
        String sql = "select * from user where username = ? and password = ?";

        // 获取PreparedStatement对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 设置参数 ? 的值
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);
        System.out.println(sql);

        // 执行sql
        ResultSet rs = pstmt.executeQuery();

        // 判断登录是否成功
        if(rs.next()){
    
    
            System.out.println("登录成功~");
        }else{
    
    
            System.out.println("登录失败~");
        }

        // 释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
}

Running results: SQL injection failed, login failed

Insert image description here

PreparedStatement prevents SQL injection by escaping special characters. The escaped SQL statement is as follows:

select * from user where username = 'zhangsan' and password = '\'or \'1\' = \'1'

3.5.4 PreparedStatement principle

PreparedStatement benefits:

  • Pre-compiled SQL for higher performance
  • Prevent SQL injection: escape sensitive characters

The Java code operation database process is as shown in the figure:

Insert image description here
The steps for Java code to operate the database are as follows:

  • Send sql statement to MySQL server

  • The MySQL server will perform the following operations on the sql statement

    • Check SQL statement

      Check whether the syntax of the SQL statement is correct

    • Compile SQL statements into executable functions

      Checking the SQL and compiling the SQL takes longer than executing the SQL. If we just reset the parameters, checking the SQL statement and compiling the SQL statement will not need to be repeated. This improves performance.

    • Execute SQL statement

Next, let’s take a look at the principle by querying the mysql log:

1. Turn on the pre-compilation function

You need to add the following parameters when writing the url:

useServerPrepStmts=true

2. Configure MySQL execution log (effective after restarting the mysql service)

In the MySQL installation path, findmy.ini, and modify the log-related content as follows:

# General and Slow logging.
log-output=FILE
general-log=1
general_log_file="D:\mysqlLog\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysqlLog\mysql-slow.log"
long_query_time=2

Insert image description here

Win+R Enter services.msc Open the service, find the MySQL service and restart it. Check whether the file is generated in the log path just configured. If it is generated, the configuration has taken effect.

Insert image description here

Insert image description here

3. Write test code

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

public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 获取连接,useServerPrepStmts=true 参数开启预编译功能
        String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useServerPrepStmts=true&allowPublicKeyRetrieval=true";
        String username = "root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 接收用户输入的用户名和密码
        String name = "zhangsan";
        String pwd = "' or '1' = '1";

        // 定义sql
        String sql = "select * from user where username = ? and password = ?";

        // 获取PreparedStatement对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 执行第一次查询
        // Thread.sleep(5000);
        ResultSet rs = null;
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);
        rs = pstmt.executeQuery();

        // 执行第二次查询
        pstmt.setString(1,"abc");
        pstmt.setString(2,"123");
        rs = pstmt.executeQuery();

        // 判断登录是否成功
        if(rs.next()){
    
    
            System.out.println("登录成功~");
        }else{
    
    
            System.out.println("登录失败~");
        }

        // 释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
}

After running the code, open the mysql.log file and view the printed content:

Among the three lines of statements in the circle in the picture below, the first line of Prepare is to precompile the SQL statement. The second and third lines execute the SQL statement twice, and the SQL is not precompiled before the second execution.

Insert image description here

Summarize:

  • When obtaining the PreparedStatement object, send the sql statement to the mysql server for checking and compilation (these steps are time-consuming)
  • You don’t have to go through these steps when executing, and it’s faster.
  • If the sql template is the same, it only needs to be checked and compiled once.

4. Database connection pool

4.1 Overview of database connection pool

1. Concept of database connection pool:

  • The database connection pool is a container responsible for allocating and managing database connections (Connection)
  • It allows an application to reuse an existing database connection instead of establishing a new one.
  • Release database connections whose idle time exceeds the maximum idle time to avoid missing database connections caused by not releasing the database connections.

2. Benefits of using database connection pool:

  • Resource reuse
  • Improve system response speed
  • Avoid missing database connections

Before we used connections in our code, we created a Connection object without using it, and it will be destroyed after use. This repeated creation and destruction process consumes computer performance and time. After the database uses the database connection pool, it can achieve the reuse of Connection objects, as shown below:

Insert image description here
The connection pool creates some connection objects at the beginning and stores them. When users need to connect to the database, they do not need to create a connection themselves, but only need to obtain a connection from the connection pool for use, and then return the connection object to the connection pool after use. This can reuse resources and save frequent creation. The time it takes for the connection to be destroyed improves the speed of system response.

3. Implementation of database connection pool

Standard interface:DataSource

The official (SUN) standard interface for database connection pools is implemented by third-party organizations. This interface provides the function of obtaining connections:

Connection getConnection()

Then there is no need to obtain the object through the DriverManager object, but through the connection pool () object. ConnectionDataSourceConnection

4. Common database connection pools

  • DBCP
  • C3P0
  • Druid(commonly used)

4.2 Use of Driud

Druid:

  • Druid connection pool is Alibaba's open source database connection pool project
  • With powerful functions and excellent performance, it is one of the best database connection pools in Java language.

The steps to use Driud are as follows:

  • Import the jar package, such as druid-1.2.9.jar
  • Define configuration file
  • Load configuration file
  • Get the database connection pool object
  • Get connection

1.jar package download

Driud jar package download address:https://repo1.maven.org/maven2/com/alibaba/druid/

Scroll to the end, find the latest version of the jar package, and click to download:druid-1.2.9.jar

Insert image description here

Insert image description here

2. Import the jar package, that is, drag druid-1.2.9.jar into the project's lib folder and add it as a library file

Insert image description here

In the 3.src directory, create a new driud.propertiesconfiguration file

Insert image description here

Insert image description here

4. Writedriud.properties configuration file with the following content:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/itheima?useSSL=false&useServerPrepStmts=true
username=root
password=123456
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

5. Write druid code

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * Druid数据库连接池演示
 */
public class JDBCDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        // 获取用户当前的工作目录
        // System.out.println(System.getProperty("user.dir"));

        // 1.导入jar包
        // 2.定义配置文件
        // 3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/driud.properties"));

        // 4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        // 5.获取数据库连接 Connection
        Connection connection = dataSource.getConnection();
        System.out.println(connection); // 获取到了连接后就可以继续做其他操作了

    }
}

Tips: You can use System.getProperty("user.dir") to get the user's current working directory to know the relative path of the loaded file.

5. Case exercises

5.1 Data preparation

Requirements: Complete the addition, deletion, modification and query operations of product brand data

  • Query: Query all data
  • Add: add brand
  • Modify: modify according to id
  • Delete: delete based on id

1.Create database tabletb_brand

-- 删除tb_brand表
drop table if exists tb_brand;

-- 创建tb_brand表
create table tb_brand (
    id int primary key auto_increment, -- id主键
    brand_name varchar(20), -- 品牌名称
    company_name varchar(20), -- 企业名称
    ordered int, -- 排序字段
    description varchar(100), -- 描述信息
    status int -- 状态:0:禁用  1:启用
);

-- 向tb_brand表插入数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1);
       
-- 查询tb_brand表
select * from tb_brand;

Insert image description here

2. Create entity classes under the pojo packageBrand

package com.itheima.pojo;

/**
 * 品牌
 * 在实体类中,基本数据类型建议使用其对应的包装类型
 */
public class Brand {
    
    

    private Integer id; // id 主键
    private String brandName;  // 品牌名称
    private String companyName; // 企业名称
    private Integer ordered; // 排序字段
    private String description; // 描述信息
    private Integer status;  // 状态:0:禁用  1:启用

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer id) {
    
    
        this.id = id;
    }

    public String getBrandName() {
    
    
        return brandName;
    }

    public void setBrandName(String brandName) {
    
    
        this.brandName = brandName;
    }

    public String getCompanyName() {
    
    
        return companyName;
    }

    public void setCompanyName(String companyName) {
    
    
        this.companyName = companyName;
    }

    public Integer getOrdered() {
    
    
        return ordered;
    }

    public void setOrdered(Integer ordered) {
    
    
        this.ordered = ordered;
    }

    public String getDescription() {
    
    
        return description;
    }

    public void setDescription(String description) {
    
    
        this.description = description;
    }

    public Integer getStatus() {
    
    
        return status;
    }

    public void setStatus(Integer status) {
    
    
        this.status = status;
    }

    @Override
    public String toString() {
    
    
        return "Brand{" +
                "id=" + id +
                ", brandName='" + brandName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}

The project structure is as follows:

Insert image description here

5.2 Query all

/**
 * 查询所有
 * 1. SQL:select * from tb_brand;
 * 2. 参数:不需要
 * 3. 结果:List<Brand>
 */
@Test
public void selectAll() throws Exception{
    
    

    // 加载配置文件,并获取连接池对象
    Properties prop = new Properties();
    prop.load(new FileInputStream("src/driud.properties"));
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    // 获取数据库连接
    Connection conn = dataSource.getConnection();

    // 定义sql
    String sql = "select * from tb_brand";

    // 获取PreparedStatement对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    // 执行查询语句
    ResultSet rs = pstmt.executeQuery();
    List<Brand> brandList = new ArrayList<>();
    Brand brand = null;

    while (rs.next()){
    
    
        // 获取数据
        int id = rs.getInt("id");
        String brandName = rs.getString("brand_name");
        String companyName = rs.getString("company_name");
        int ordered = rs.getInt("ordered");
        String description = rs.getString("description");
        int status = rs.getInt("status");

        //封装Brand对象
        brand = new Brand();
        brand.setId(id);
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
        brand.setOrdered(ordered);
        brand.setDescription(description);
        brand.setStatus(status);

        // 存入集合
        brandList.add(brand);
    }

    System.out.println(brandList);

    // 释放资源
    rs.close();
    pstmt.close();
    conn.close();
}
    

The running results are as follows:

Insert image description here

5.3 Add data

/**
 * 添加
 * 1. SQL:insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);
 * 2. 参数:需要,除了id之外的所有参数信息
 * 3. 结果:boolean
 */
@Test
public void add() throws Exception{
    
    

    // 页面提交的数据
    String brandName = "香飘飘";
    String companyName = "香飘飘";
    int ordered = 1;
    String description = "绕地球一圈";
    int status = 1;

    // 加载配置文件,并获取连接池对象
    Properties prop = new Properties();
    prop.load(new FileInputStream("src/driud.properties"));
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    // 获取数据库连接
    Connection conn = dataSource.getConnection();

    // 定义sql
    String sql = "insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?)";

    // 获取PreparedStatement对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    // 设置参数
    pstmt.setString(1,brandName);
    pstmt.setString(2,companyName);
    pstmt.setInt(3,ordered);
    pstmt.setString(4,description);
    pstmt.setInt(5,status);

    // 执行插入语句
    int count = pstmt.executeUpdate();
    System.out.println(count > 0);

    // 释放资源
    pstmt.close();
    conn.close();
}

After running the above code, query the brand table:

Insert image description here

5.4 Modify data

/**
 * 修改
 * 1. SQL:
 update tb_brand
 set brand_name = ?, company_name  = ?, ordered = ?, description = ?, status = ?
 where id = ?
 * 2. 参数:需要,所有数据
 * 3. 结果:boolean
 */
@Test
public void update() throws Exception{
    
    

    // 页面提交的数据
    String brandName = "香飘飘";
    String companyName = "香飘飘";
    int ordered = 1000;
    String description = "绕地球三圈";
    int status = 1;
    int id = 4;

    // 加载配置文件,并获取连接池对象
    Properties prop = new Properties();
    prop.load(new FileInputStream("src/driud.properties"));
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    // 获取数据库连接
    Connection conn = dataSource.getConnection();

    // 定义sql
    String sql = "update tb_brand\n" +
            "set brand_name = ?, company_name  = ?, ordered = ?, description = ?, status = ?\n" +
            "where id = ?";

    // 获取PreparedStatement对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    // 设置参数
    pstmt.setString(1,brandName);
    pstmt.setString(2,companyName);
    pstmt.setInt(3,ordered);
    pstmt.setString(4,description);
    pstmt.setInt(5,status);
    pstmt.setInt(6,id);

    // 执行更新语句
    int count = pstmt.executeUpdate();
    System.out.println(count > 0);

    // 释放资源
    pstmt.close();
    conn.close();
}

After running the above code, query the brand table:

Insert image description here

5.5 Deletion of data

/**
 * 删除
 * 1. SQL:delete from tb_brand where id = ?
 * 2. 参数:需要,id
 * 3. 结果:boolean
 */
@Test
public void deleteById() throws Exception{
    
    

    // 页面提交的数据
    int id = 4;

    // 加载配置文件,并获取连接池对象
    Properties prop = new Properties();
    prop.load(new FileInputStream("src/driud.properties"));
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    // 获取数据库连接
    Connection conn = dataSource.getConnection();

    // 定义sql
    String sql = "delete from tb_brand where id = ?";

    // 获取PreparedStatement对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    // 设置参数
    pstmt.setInt(1,id);

    // 执行删除语句
    int count = pstmt.executeUpdate();
    System.out.println(count > 0);

    // 释放资源
    pstmt.close();
    conn.close();
}

After running the above code, query the brand table:

Insert image description here

Guess you like

Origin blog.csdn.net/aidijava/article/details/131947708