Detailed explanation of JDBC (many examples)

JDBC

The concept of JDBC

1. The concept of jdbc

JDBC (Java DataBaseConnectivity java database connection) is a Java API for executing SQL statements, which can provide unified access to various relational databases. It is composed of a set of classes and interfaces written in Java language.

2. The essence of jdbc

In fact, it is a set of specifications (interfaces) officially provided by java. It is used to help developers quickly realize the connection of different relational databases!

Quick Start with JDBC

Quick start steps for jdbc:

1. Import the jar package

2. Register the driver

3. Get the database connection

4. Get the executor object

5. Execute the sql statement and return the result

6. Processing results

7. Release resources

Sample code:

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

public class JDBC_index1 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");//MySQL5以后可直接省略
        //获取数据库连接
        Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306/cadastre","root","XXXXXX");
        //获取执行者对象
        Statement stat=con.createStatement();
        //执行sql语句并返回结果
        String sql="select * from 网易云热评";
        ResultSet re=stat.executeQuery(sql);
        //处理结果
        while (re.next()){
    
    
      System.out.println(re.getString("userId")+"\t"+re.getString("nickname")+"\t"+re.getString("content"));
        }
        //释放资源
        con.close();
    }
}

Detailed explanation of JDBC function

1. DriverManager drive management object

(1) Register driver: (driver can be omitted directly after mysql5)
1. Register a given driver: staticvoid registerDriver(Driver driver);

2. Write code using: Class.forName(“com.mysql.jdbc.Driver”);

3. There is a static code block in the com.mysql.jdbc.Driver class

(2) Get the database connection:
1. Get the database connection object: static ConnectiongetConnection(Stringurl, String user, String password);

2. Return value: Connection database connection object

3. Parameter
url: Specify the connection path. Syntax: jdbc:mysql://ip address (domain name): port number/database name

​ user: username

​ password: password

2. Connection database connection object

1. Get the executor object:
Get the common executor object: Statement createStatement0;
Get the precompiled executor object: PreparedStatement prepareStatement(String sql);

2. Manage transactions
Start a transaction: setAutoCommit(boolean autoCommit); if the parameter is false, start a transaction

​ Commit the transaction: commit();

​ Rollback transaction: rollback();

3. Release resources
Immediately release the database connection object: void close();

3. Statement executes the object of the sql statement

(1) Execute DML statement: int executeUpdate(String sql);

Return Value int: Returns the number of rows affected.

Parameter sql: insert, update, delete statements can be executed.

(2) Execute the DQL statement: ResultSet executeQuery(String sql);

Return value ResultSet: encapsulates the result of the query.

Parameter sql: select statement can be executed.

(3) Release resources
Immediately release the database connection object: void close();

4. ResultSet result set object

1. Determine whether there is still data in the result set: boolean next();

has data returns true and moves the index down one row. No data returns false.

2. Get the data in the result set: XXX getXxx("column name"); XXX represents the data type (to get a certain column of data, the data type of this column).

例如: String getString(“name”);int getInt(" age");

3. Release resources

Immediately release the result set object: void close();

JDBC case

case requirements

Use JDBC to complete the CRUD operation on the student table

data preparation

1. Database data preparation

-- 创建数据库
create DATABASE db14;

-- 使用数据库
use db14

-- 创建student表
CREATE TABLE student
(
   id int PRIMARY KEY,
	 sname VARCHAR(20),
   age int,
	 brithday date
);

-- 添加数据
INSERT into student VALUES(1,'张飞',23,'1999-08-11'),(2,'李四',23,'1998-08-11'),(3,'王五',23,'1997-08-11'),(4,'关羽',23,'1995-08-11');

2. Create a student class

package Com.Stuclass;

import java.util.Date;

public class Student {
    
    
    private Integer id;
    private String sname;
    private Integer age;
    private Date birthday;

    public Student(Integer id, String sname, Integer age, Date birthday) {
    
    
        this.id = id;
        this.sname = sname;
        this.age = age;
        this.birthday = birthday;
    }

    public Integer getId() {
    
    
        return id;
    }

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

    public String getSname() {
    
    
        return sname;
    }

    public void setSname(String sname) {
    
    
        this.sname = sname;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    public Date getBirthday() {
    
    
        return birthday;
    }

    public void setBirthday(Date birthday) {
    
    
        this.birthday = birthday;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "id=" + id +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}

function realization

1. Query all student information

public ArrayList<Student> findAll() {
    
    
        ArrayList<Student> list=new ArrayList<>();
        Connection con=null;
        try {
    
    
            con= DriverManager.getConnection(conName,name,password);
            Statement statement = con.createStatement();
            String sql="select * from student";
            ResultSet resultSet = statement.executeQuery(sql);
            while (resultSet.next()){
    
    
                Integer id=resultSet.getInt("id");
                String sname=resultSet.getString("sname");
                Integer age=resultSet.getInt("age");
                Date birthday=resultSet.getDate("brithday");
                Student s=new Student(id,sname,age,birthday);
                list.add(s);
            }
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        return list;
    }

2. Query student information through ID

public Student findById(Integer id) {
    
    
        Connection con=null;
        Student s = null;
        try{
    
    
            con=DriverManager.getConnection(conName,name,password);
            String sql="select * from student where id=?";
            PreparedStatement pstate = con.prepareStatement(sql);
            pstate.setInt(1,id);
            ResultSet resultSet = pstate.executeQuery();
            while (resultSet.next()){
    
    
                s=new Student(id,resultSet.getString("sname"),resultSet.getInt("age"),resultSet.getDate("brithday"));
            }
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        return s;
    }

3. Add student records

public int insert(Integer id, String sname, Integer age, String  birthday) {
    
    
        Connection con=null;
        int re=0;
        Date date=new Date();//需要new一个Date对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //设置日期格式  yyyy-MM-dd-HH-mm-ss这个是完整的
        try {
    
    
            date = dateFormat.parse(birthday);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
        }
        try {
    
    
            con= JDBCUtils.getConnect();
            String sql="insert into student values(?,?,?,?)";
            PreparedStatement p=con.prepareStatement(sql);
            p.setInt(1,id);
            p.setString(2,sname);
            p.setInt(3,age);
            p.setDate(4, new java.sql.Date(date.getTime()));
            re = p.executeUpdate();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        return re;
    }

4. Modify student information

 public int update(String name1,Integer age) {
    
    
        Connection con=null;
        int result=0;
        String sql="update student " +
                "set age=? " +
                "where sname=?";
        try {
    
    
            con= JDBCUtils.getConnect();
            PreparedStatement p = con.prepareStatement(sql);
            p.setInt(1,age);
            p.setString(2,name1);
            result = p.executeUpdate();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        return result;
    }

5. Delete student records

public int delete(Integer id) {
    
    
        Connection con=null;
        int result=0;
        try {
    
    
            con= JDBCUtils.getConnect();
            String sql="delete from student where id=?";
            PreparedStatement p = con.prepareStatement(sql);
            p.setInt(1,id);
            result = p.executeUpdate();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        return result;
    }

It is recommended to use tools

Configuration information: (create a config.properties file in the src directory)

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db14
username=root
password=XXXXXXx

Tools:

package Com.Stuclass.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/*
* JDBC工具类
* */
public class JDBCUtils {
    
    
//    1、构造方法私有
    private JDBCUtils(){
    
    }
//    2、声明所需要的配置变量
    private static String driverClass;
    private static String url;
    private static String username;
    private static String password;
    private static Connection con;

//    3、提供静态代码块,读取配置文件信息为变量赋值,注册驱动
     static {
    
    
        try {
    
    
//            赋值
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
            Properties pro=new Properties();
            pro.load(is);
            driverClass=pro.getProperty("driverClass");
            url=pro.getProperty("url");
            username=pro.getProperty("username");
            password=pro.getProperty("password");
//            注册驱动
            Class.forName(driverClass);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
}

//        获取数据库连接
    public static Connection getConnect(){
    
    
        try {
    
    
            con= DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return con;
    }
//    关闭连接
    public static void close(Connection con, Statement state, ResultSet rs){
    
    
        if (con!=null){
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (state!=null){
    
    
            try {
    
    
                state.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (rs!=null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    public static void close(Connection con, Statement state){
    
    
        if (con!=null){
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (state!=null){
    
    
            try {
    
    
                state.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

SQL injection attack

Attack the system by exploiting SQL statement vulnerabilities

For example:

According to normal principles, all the content we enter in the password should be considered as the composition of the password

But now the Statement object executes part of the password as a query condition when executing the SQL statement

Solution:

Use precompiled SQL statements

JDBC transaction management

How JDBC manages transactions

Functional class for managing transactions: Connection

​ Start a transaction: setAutoCommit(boolean autoCommit); if the parameter is false, start a transaction.

​ Commit the transaction: commit();

​ Rollback transaction: rollback();

database connection pool

1. Background of database connection
Database connection is a critical, limited, and expensive resource, which is particularly prominent in multi-user web applications. The management of database connections can significantly affect the performance indicators of the entire application. , the database connection pool is proposed for this problem

2. Database connection pool
The database connection pool is responsible for allocating, managing and releasing database connections, which allows an application to reuse an existing database connection instead of re-establishing one. This technology can significantly improve the performance of database operations

Custom database connection pool

1. DataSource interface overview
javax.sql.DataSource interface: data source (database connection pool).

The database connection pool specification (interface) officially provided by Java If you want to complete the database connection pool technology, you must implement the DataSource interface

Core function: get database connection object: Connection getConnection();

2. Custom database connection pool

Define a class that implements the DataSource interface.

Define a container for storing multiple Connection objects.

Define a static code block, obtain 10 connections through the JDBC tool class and save them in the container.

Override the getConnection method to get a connection from the container and return it.

Define the getSize method to get the size of the container and return it.

Prepare:

The above JDBCutil tool class and related configuration files

Example:

package JDBCplus.Demo1;
/*
* 自定义数据库连接池
* */
import JDBCplus.JDBCUtils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

public class MyDataSource implements DataSource {
    
    
//    1、准备容器  注意必须是线程安全的
    private static List<Connection> pool= Collections.synchronizedList(new ArrayList<>());
//    2、通过工具类获取10个连接对象
    static {
    
    
    for (int i = 0; i < 10; i++) {
    
    
        Connection con= JDBCUtils.getConnect();
        pool.add(con);
    }
}
//    3、重写getConnection方法

    @Override
    public Connection getConnection() throws SQLException {
    
    
        if (pool.size()>0){
    
    
            return pool.remove(0);
        }else {
    
    
            throw new RuntimeException("连接池已空");
        }
    }
//    4、定义getSize方法获取连接池大小
    public int getSize(){
    
    
        return pool.size();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
    
    
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
    
    
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
    
    
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
    
    
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
    
    

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
    
    

    }

    @Override
    public int getLoginTimeout() throws SQLException {
    
    
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    
    
        return null;
    }
}

Use test:

package JDBCplus.Demo1;

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

public class Test {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        MyDataSource myDataSource = new MyDataSource();
        Connection con=myDataSource.getConnection();
        String sql="select * from student";
        Statement statement = con.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
    
    
            System.out.println(resultSet.getInt("id")+" "+resultSet.getString("sname"));
        }
        resultSet.close();
        statement.close();
        con.close();
    }
}

image-20221013150926078

return link

Ways to return the database connection:

Inheritance

Decorator Design Pattern

Adapter design pattern

Dynamic Proxy

Return Connection - Inheritance Method

1. The inheritance method returns the idea of ​​database connection.

By printing the connection object, it is found that the connection implementation class obtained by DriverManager is JDBC4Connection, then we can customize a class, inherit the JDBC4Connection class, and rewrite the close() method to complete the return of the connection object.

2. The inheritance method returns the implementation steps of the database connection.

1 Define a class that inherits JDBC4Connection.

2 Define the member variables of the Connection connection object and the connection pool container object.

3 Complete the assignment of member variables through the parameterized construction method.

4 Rewrite the close method and add the connection object to the pool.

3. Inheritance mode returns the problem of database connection.

By looking at the method of obtaining the connection of the JDBC tool class, it is found that although we have customized a subclass, we have completed the operation of returning the connection. But what DriverManager acquires is JDBC4Connection object, not our subclass object, and we can’t modify the functions of classes in the driver package as a whole, so the inherited method won’t work!

(The JDBC4Connection class is not found in my MySQL package here and cannot be displayed)

Return Connections - Decorator Design Pattern

1. The decoration design pattern returns the idea of ​​database connection.

We can customize a class to implement the Connection interface.

In this way, it has the same behavior as JDBC4Connection and rewrites the close() method to complete the return of the connection. Other functions can also call the original methods of the mysql driver package implementation class.

2. The decoration design pattern returns the implementation steps of the database connection.

1. Define a class that implements the Connection interface

2. Define the member variables of the Connection connection object and the connection pool container object

3. Complete the assignment of member variables through the parameterized construction method

4. Rewrite the close() method and add the connection object to the pool

5. For the remaining methods, you only need to call the connection object of the mysql driver package to complete

6. In the custom connection pool, wrap the obtained connection object with a custom connection object

3. The decoration design mode returns the problems existing in the database connection.

After implementing the Connection interface, there are a large number of methods that need to be rewritten in the custom class

Sample code:

package JDBCplus.Demo2;

import java.sql.*;
import java.util.*;
import java.util.concurrent.Executor;

public class MyConnection2 implements Connection {
    
    
//    定义连接对象和连接池对象
    private Connection con;
    private List<Connection> pool;

//    构造方法赋值
    public MyConnection2(Connection con,List<Connection> pool){
    
    
        this.con=con;
        this.pool=pool;
    }
//     重写close方法
    @Override
    public void close() throws SQLException {
    
    
        pool.add(con);
    }

    @Override
    public Statement createStatement() throws SQLException {
    
    
        return con.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
    
    
        return con.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
    
    
        return con.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
    
    
        return con.nativeSQL(sql);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
    
    
        con.setAutoCommit(false);
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
    
    
        return con.getAutoCommit();
    }

    @Override
    public void commit() throws SQLException {
    
    
        con.commit();
    }

    @Override
    public void rollback() throws SQLException {
    
    
        con.rollback();
    }



    @Override
    public boolean isClosed() throws SQLException {
    
    
        return con.isClosed();
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
    
    
        return con.getMetaData();
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
    
    
         con.setReadOnly(false);
    }

    @Override
    public boolean isReadOnly() throws SQLException {
    
    
        return con.isReadOnly();
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
    
    
        con.setCatalog(catalog);
    }

    @Override
    public String getCatalog() throws SQLException {
    
    
        return con.getCatalog();
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
    
    
        con.setTransactionIsolation(level);
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
    
    
        return con.getTransactionIsolation();
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
    
    
        return con.getWarnings();
    }

    @Override
    public void clearWarnings() throws SQLException {
    
    
        con.clearWarnings();
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.createStatement(resultSetType,resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.prepareStatement(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.prepareCall(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
    
    
        return con.getTypeMap();
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
    
    
        con.setTypeMap(map);
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
    
    
        con.setHoldability(holdability);
    }

    @Override
    public int getHoldability() throws SQLException {
    
    
        return con.getHoldability();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
    
    
        return con.setSavepoint();
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
    
    
        return con.setSavepoint(name);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
    
    
        con.rollback();
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    
    
        con.releaseSavepoint(savepoint);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.prepareStatement(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    
    
        return con.prepareStatement(sql,autoGeneratedKeys);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
    
    
        return con.prepareStatement(sql,columnIndexes);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
    
    
        return con.prepareStatement(sql,columnNames);
    }

    @Override
    public Clob createClob() throws SQLException {
    
    
        return con.createClob();
    }

    @Override
    public Blob createBlob() throws SQLException {
    
    
        return con.createBlob();
    }

    @Override
    public NClob createNClob() throws SQLException {
    
    
        return con.createNClob();
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
    
    
        return con.createSQLXML();
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
    
    
        return con.isValid(timeout);
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
    
    
        con.setClientInfo(name,value);
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
    
    
        con.setClientInfo(properties);
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
    
    
        return con.getClientInfo(name);
    }

    @Override
    public Properties getClientInfo() throws SQLException {
    
    
        return con.getClientInfo();
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
    
    
        return con.createArrayOf(typeName,elements);
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
    
    
        return con.createStruct(typeName,attributes);
    }

    @Override
    public void setSchema(String schema) throws SQLException {
    
    
        con.setSchema(schema);
    }

    @Override
    public String getSchema() throws SQLException {
    
    
        return con.getSchema();
    }

    @Override
    public void abort(Executor executor) throws SQLException {
    
    
        con.abort(executor);
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
    
    
        con.setNetworkTimeout(executor,milliseconds);
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
    
    
        return con.getNetworkTimeout();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
    
    
        return con.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
    
    
        return con.isWrapperFor(iface);
    }
}

Change MyDataSouce (database connection pool method):

//    3、重写getConnection方法

    @Override
    public Connection getConnection() throws SQLException {
    
    
        if (pool.size()>0){
    
    
            Connection con = pool.remove(0);
            MyConnection2 myCon=new MyConnection2(con,pool);
            return myCon;
        }else {
    
    
            throw new RuntimeException("连接池已空");
        }
    }

Test code:

package JDBCplus.Demo1;

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

public class Test {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        MyDataSource myDataSource = new MyDataSource();
        System.out.println(myDataSource.getSize());
        Connection con=myDataSource.getConnection();
        System.out.println(myDataSource.getSize());
        System.out.println(con.getClass());
        String sql="select * from student";
        Statement statement = con.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
    
    
            System.out.println(resultSet.getInt("id")+" "+resultSet.getString("sname"));
        }
        resultSet.close();
        statement.close();
        con.close();
        System.out.println(myDataSource.getSize());
    }
}
image-20221013164305855

It is found that the parent class is a custom class, and the connection pool size is 10 after use

Return Connection - Adapter Design Pattern

1. The adapter design pattern returns the idea of ​​database connection.

We can provide an adapter class that implements the Connection interface and implements all methods (except the close method

The custom connection class only needs to inherit this adapter class and rewrite the close method that needs to be improved

2. The adapter design pattern returns the implementation steps of the database connection.

1 Define an adapter class that implements the Connection interface.

2 Define the member variables of the Connection connection object.

3 Complete the assignment of member variables through the parameterized construction method.

4 Rewrite all methods (except close), and call the connection object of the mysq driver package to complete.

5 Define a connection class and inherit the adapter class.

6 Define the member variables of the Connection connection object and the connection pool container object, and assign values ​​through the parameterized construction.

7 Rewrite the close() method to return the connection.

8 In the custom connection pool, wrap the acquired connection object with a custom connection object.

3. The adapter design pattern returns the problems existing in the database connection.

Although the custom connection class is very concise, the adapter class is still written by ourselves, which is more troublesome

Sample code:

Adapter class: (override all methods except close, abstract class)

package JDBCplus.Dome3;

import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

/*
* 适配器类
* */
public abstract class MyAdapter implements Connection{
    
    
    private Connection con;
    public MyAdapter(Connection con){
    
    
        this.con=con;
    }
    @Override
    public Statement createStatement() throws SQLException {
    
    
        return con.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
    
    
        return con.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
    
    
        return con.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
    
    
        return con.nativeSQL(sql);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
    
    
        con.setAutoCommit(false);
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
    
    
        return con.getAutoCommit();
    }

    @Override
    public void commit() throws SQLException {
    
    
        con.commit();
    }

    @Override
    public void rollback() throws SQLException {
    
    
        con.rollback();
    }



    @Override
    public boolean isClosed() throws SQLException {
    
    
        return con.isClosed();
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
    
    
        return con.getMetaData();
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
    
    
        con.setReadOnly(false);
    }

    @Override
    public boolean isReadOnly() throws SQLException {
    
    
        return con.isReadOnly();
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
    
    
        con.setCatalog(catalog);
    }

    @Override
    public String getCatalog() throws SQLException {
    
    
        return con.getCatalog();
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
    
    
        con.setTransactionIsolation(level);
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
    
    
        return con.getTransactionIsolation();
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
    
    
        return con.getWarnings();
    }

    @Override
    public void clearWarnings() throws SQLException {
    
    
        con.clearWarnings();
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.createStatement(resultSetType,resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.prepareStatement(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    
    
        return con.prepareCall(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
    
    
        return con.getTypeMap();
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
    
    
        con.setTypeMap(map);
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
    
    
        con.setHoldability(holdability);
    }

    @Override
    public int getHoldability() throws SQLException {
    
    
        return con.getHoldability();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
    
    
        return con.setSavepoint();
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
    
    
        return con.setSavepoint(name);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
    
    
        con.rollback();
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    
    
        con.releaseSavepoint(savepoint);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.prepareStatement(sql,resultSetType,resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    
    
        return con.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    
    
        return con.prepareStatement(sql,autoGeneratedKeys);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
    
    
        return con.prepareStatement(sql,columnIndexes);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
    
    
        return con.prepareStatement(sql,columnNames);
    }

    @Override
    public Clob createClob() throws SQLException {
    
    
        return con.createClob();
    }

    @Override
    public Blob createBlob() throws SQLException {
    
    
        return con.createBlob();
    }

    @Override
    public NClob createNClob() throws SQLException {
    
    
        return con.createNClob();
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
    
    
        return con.createSQLXML();
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
    
    
        return con.isValid(timeout);
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
    
    
        con.setClientInfo(name,value);
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
    
    
        con.setClientInfo(properties);
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
    
    
        return con.getClientInfo(name);
    }

    @Override
    public Properties getClientInfo() throws SQLException {
    
    
        return con.getClientInfo();
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
    
    
        return con.createArrayOf(typeName,elements);
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
    
    
        return con.createStruct(typeName,attributes);
    }

    @Override
    public void setSchema(String schema) throws SQLException {
    
    
        con.setSchema(schema);
    }

    @Override
    public String getSchema() throws SQLException {
    
    
        return con.getSchema();
    }

    @Override
    public void abort(Executor executor) throws SQLException {
    
    
        con.abort(executor);
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
    
    
        con.setNetworkTimeout(executor,milliseconds);
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
    
    
        return con.getNetworkTimeout();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
    
    
        return con.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
    
    
        return con.isWrapperFor(iface);
    }
}

Custom connection class:

package JDBCplus.Dome3;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/*
* 自定义连接类
* */
public class MyConnection3 extends MyAdapter {
    
    
    //    定义连接对象和连接池对象
    private Connection con;
    private List<Connection> pool;

    //    构造方法赋值
    public MyConnection3(Connection con,List<Connection> pool) {
    
    
        super(con);
        this.con=con;
        this.pool=pool;
    }

    @Override
    public void close() throws SQLException {
    
    
        pool.add(con);
    }
}

Database connection pool changes:

//    3、重写getConnection方法

    @Override
    public Connection getConnection() throws SQLException {
    
    
        if (pool.size()>0){
    
    
            Connection con = pool.remove(0);
            MyConnection3 myCon=new MyConnection3(con,pool);
            return myCon;
        }else {
    
    
            throw new RuntimeException("连接池已空");
        }
    }

Test code:

(same as decorator design pattern)

image-20221013170409082

target reached

dynamic proxy

Dynamic proxy:

Enhance a method without changing the method of the target object

composition:

Proxied object: real object

Proxy object: an object in memory

Require:

The proxy object must implement the same interface as the proxy object

Example:

student class:

package proxy;

public class Student implements StudentInterface{
    
    
    @Override
    public void eat(String name){
    
    
        System.out.println("学生吃"+name);
    }
    @Override
    public void study(){
    
    
        System.out.println("在家自学");
    }
}

StudentInterface interface:

package proxy;

public interface StudentInterface {
    public void eat(String name);
    public void study();
}

test:

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();
        student.study();
        student.eat("米饭");
        /*
        * 要求不改动Student的代码,更改study方法的输出内容
        * */
        //参数一:类加载器,参数二:接口类型class数组,参数三:代理规则
        StudentInterface proxy= (StudentInterface) Proxy.newProxyInstance(student.getClass().getClassLoader(), new Class[]{
    
    StudentInterface.class}, new InvocationHandler() {
    
    
            /*
            * 执行student类中所有的方法都会经过invoke方法
            * 对method方法判断,修改想要的方法
            * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                if(method.getName().equals("study")){
    
    
                    System.out.println("不去学习");
                    return null;
                }else {
    
    
                    return method.invoke(student,args);
                }
            }
        });
        proxy.eat("米饭");
        proxy.study();
    }
}

operation result:

image-20221013173931028

modified successfully

The dynamic proxy returns the database connection:

1. The idea of ​​returning the database connection in the dynamic proxy mode.

We can use Proxy to complete the proxying of Connection implementation class objects

In the proxy process, it is judged that if the close method is executed, the connection will be returned to the pool.

If it is another method, just call the original function of the connection object

2. The implementation steps of returning the database connection in the dynamic proxy mode.

Define a class that implements the DataSource interface

Define a container for saving multiple Connection connection objects

Define a static code block, obtain 10 connections and save them in the container through the JDBC tool class

Override the getConnection method to get a connection from the container

Through the Proxy proxy, if it is a close method, the connection will be returned to the pool. If it is another method, call the original function

Define the getSize method to get the size of the container and return

Realize rewriting the getConnection method in MyDataSource (implemented using dynamic proxy)

//   3、重写getConnection方法   使用动态代理方式实现
    @Override
    public Connection getConnection() throws SQLException {
    
    
        if (pool.size()>0){
    
    
            Connection con = pool.remove(0);
            Connection myCon = (Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), new Class[]{
    
    Connection.class}, new InvocationHandler() {
    
    
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                    if (method.getName().equals("close")){
    
    
                        pool.add(con);
                        return null;
                    }else {
    
    
                        return method.invoke(con,args);
                    }
                }
            });
            return myCon;
        }else {
    
    
            throw new RuntimeException("连接池已空");
        }
    }

Use the test code above:

image-20221014160000515

Open source database connection pool

C3P0 database connection pool

1. The steps to use the C3PO database connection pool.

Import the jar package.

Import the configuration file to the src directory.

Create a C3PO connection pool object.

Get a database connection to use.

Note: The configuration file of C3PO will be loaded automatically, but it must be called c3p0-config.xml or c3pO-config.properties

Download the jar package:

Official website: https://sourceforge.net/projects/c3p0/files/latest/download

Other Baidu network disk: Baidu network disk download link: https://pan.baidu.com/s/1o9cBkMVb_kZmAksZjjoZYg Password: c7pr

Import the jar package:

image-20221014163706222

Import the configuration file to the src directory:

image-20221014163828508

Example usage:

package C3P0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class Test1 {
    
    
    public static void main(String[] args) throws SQLException {
    
    
//        1、创建c3p0数据库连接池
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
//        2、通过连接池获取数据库连接
        Connection con = dataSource.getConnection();
//        3、执行数据库操作
        String sql="select * from student";
        PreparedStatement p = con.prepareStatement(sql);
        ResultSet re = p.executeQuery();
        while (re.next()){
    
    
            System.out.println(re.getInt("id")+"\t"+re.getString("sname"));
        }

    }
}
image-20221014163917795

Druid database connection pool

1 Introduction

Druid (Druid) is a database connection pool developed by Alibaba known as monitoring. Druid is currently the best database connection pool . In terms of function, performance, and scalability, it surpasses other database connection pools. At the same time, log monitoring is added, which can well monitor the execution of DB pool connections and SQL. Druid has deployed more than 600 applications in Alibaba, and has passed the rigorous test of large-scale deployment in the production environment for more than a year.

1. Steps to use the Druid database connection pool:

Import the jar package.

Write a configuration file and place it in the src directory.

Load configuration files through the Properties collection.

Obtain the database connection pool object through the Druid connection pool factory class.

Get a database connection to use.

Note: Druid will not automatically load the configuration file, we need to load it manually, but the name of the file can be customized.

Download the jar package:

Other people's Baidu network disk:: https://pan.baidu.com/s/1U9v5c_DindqXva92JeRVJQ Password: nquq

Import the jar package:

image-20221014171619816

Write configuration file:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db14
username=root
password=xxxxxx
initialSize=5
maxActive=10
maxWait=3000

Sample code:

package Druid;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class test1 {
    
    
    public static void main(String[] args) throws Exception {
    
    
//        获取配置文件的流对象
        InputStream is = test1.class.getClassLoader().getResourceAsStream("druid.properties");
//        通过properties集合,加载配置文件
        Properties properties = new Properties();
        properties.load(is);
//        通过Druid连接池工厂类获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//        连接池中获取连接对象
        Connection con = dataSource.getConnection();
//        执行数据库操作
        String sql="select * from student";
        PreparedStatement p = con.prepareStatement(sql);
        ResultSet re = p.executeQuery();
        while (re.next()){
    
    
            System.out.println(re.getInt("id")+"\t"+re.getString("sname"));
        }
    }
}
image-20221014174345716

Tool class created based on Druid database connection pool

code:

package Druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DruidUtils {
    
    
//    私有化构造方法
    private DruidUtils(){
    
    }
//    声明数据源变量
    private static DataSource dataSource;
//    静态代码块完成配置文件加载和获取数据库连接对象
    static {
    
    
    InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
    Properties properties = new Properties();
    try {
    
    
        properties.load(is);
        dataSource = DruidDataSourceFactory.createDataSource(properties);
    }catch (Exception e) {
    
    
        e.printStackTrace();
    }
}
//   获取数据库连接
    public static Connection getConnection(){
    
    
        Connection con=null;
        try {
    
    
            con = dataSource.getConnection();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return con;
    }
//   获取数据库连接池
    public static DataSource getDataSource(){
    
    
        return dataSource;
    }

    //    关闭连接
    public static void close(Connection con, Statement state, ResultSet rs){
    
    
        if (con!=null){
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (state!=null){
    
    
            try {
    
    
                state.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (rs!=null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    public static void close(Connection con, Statement state){
    
    
        if (con!=null){
    
    
            try {
    
    
                con.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
        if (state!=null){
    
    
            try {
    
    
                state.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

Example usage:

package Druid;

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

public class test2 {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        Connection con=DruidUtils.getConnection();
        String sql="select * from student";
        PreparedStatement p = con.prepareStatement(sql);
        ResultSet re = p.executeQuery();
        while (re.next()){
    
    
            System.out.println(re.getInt("id")+"\t"+re.getString("sname"));
        }
    }
}
image-20221014180438643

Guess you like

Origin blog.csdn.net/qq_54353206/article/details/127325477