Tool class encapsulation, DAO pattern and custom connection pool (java)

Posted by yarons on Thu, 29 Aug 2019 14:39:47 +0200

1. Tool class encapsulation

Tool class encapsulation mainly extracts all the operations of the database and puts them in the DbUtils tool class, so as to realize code reuse. Implementing the effect of code layering and improving the logical structure of code. In order to modify the function of the module, it is necessary to modify only part of the code.

Case realization: query, add, delete and modify emp table

1.1 Write the parameters of the connection object into the configuration file by loading the driver class, load the configuration file with the class loader, and read and write the parameters through the IO stream.

Configuration file: db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8
username=root
password=root

1.2 Encapsulation of DbUtils Tool Class Encapsulation for Addition, Deletion and Amendment of emp Table

Emphasis: Query data in the database (using reflection and introspection mechanisms)

Basic step description of query: all records in query table

(1) Get the connection object conn and execute the command object pstat

(2) pstat executes the SQL statement and returns the result set to the result set object rs

(3) Get the table column name set (table header name set) through the result set object.

(4) Traverse the result set and get the corresponding value of each row and column through the column name set.

(5) Create object T = class1. newInstance () with generic class object, and obtain attribute descriptor with column name and generic class object (corresponding to each attribute in entity class).

(6) Get the setXXX() method of each attribute with the attribute descriptor, call the reflection method invoke(t,value); assign value to each attribute.

(7) Finally, the t-object is added to the list set to read the data in the database and traverse the output.

public class DbUtils {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    static{
        try {
            Properties prop = new Properties();
            InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
            prop.load(is);
            driver = prop.getProperty("driver");
            url  = prop.getProperty("url");
            username = prop.getProperty("username");
            password = prop.getProperty("password");

            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            System.out.println("Connection failed!");
            e.printStackTrace();
        }
        return null;
    }

    public static void executeUpdate(String sql,Object...params){
        Connection conn = DbUtils.getConnection();
        if(conn!=null){
            PreparedStatement pstat=null;
            try {
                pstat = conn.prepareStatement(sql);
                if(params!=null){
                    for (int i = 0; i < params.length; i++) {
                        pstat.setObject(i+1,params[i]);
                    }
                }
                pstat.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                release(conn,pstat,null);
            }
        }
    }

    public static <T> List<T> findAll(String sql, Object[] params, Class<T> class1){
        List<T> list = new ArrayList<>();
        Connection conn=null;
        PreparedStatement pstat=null;
        ResultSet rs=null;
        try {
            conn = DriverManager.getConnection(url,username,password);
            pstat = conn.prepareStatement(sql);
            rs = pstat.executeQuery();
            while(rs.next()){
                try {
                    T t = class1.newInstance();
                    ResultSetMetaData metaData = rs.getMetaData();
                    int columnCount = metaData.getColumnCount();
//                    System.out.println(columnCount);
                    for (int i = 0; i < columnCount; i++) {
                        //Get the column names for each column
                        String columnLabel = metaData.getColumnLabel(i + 1);
                        //Get the corresponding value for this row of column names
                        Object object = rs.getObject(columnLabel);
                        try {
                            //Get the attribute descriptor for each column
                            PropertyDescriptor pd = new PropertyDescriptor(columnLabel,class1);
                            if(pd!=null) {
                                //Get its set method from attribute descriptor
                                Method writeMethod = pd.getWriteMethod();
                                //Assigning the values of each column to the attributes corresponding to the entity class
                                writeMethod.invoke(t, object);
                            }
                        } catch (Exception e) {
//                            e.printStackTrace();
                            continue;
                        }
                    }
                    list.add(t);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            release(conn,pstat,rs);
        }
        return list;
    }

    public static <T> T findByEmpno(String sql,Class<T> class1,Object...params){
        Connection conn=null;
        PreparedStatement pstat=null;
        ResultSet rs=null;
        T t = null;
        try {
            conn = DriverManager.getConnection(url,username,password);
            pstat = conn.prepareStatement(sql);
            pstat.setObject(1,params[0]);
            rs = pstat.executeQuery();
            if(rs.next()){
                try {
                    t=class1.newInstance();
                    ResultSetMetaData metaData = rs.getMetaData();
                    for (int i = 0; i < metaData.getColumnCount(); i++) {
                        String columnLabel = metaData.getColumnLabel(i + 1);
                        Object value = rs.getObject(columnLabel);

                        try {
                            PropertyDescriptor pd = new PropertyDescriptor(columnLabel,class1);
                            if(pd!=null){
                                Method writeMethod = pd.getWriteMethod();
                                writeMethod.invoke(t,value);
                            }

                        } catch (IntrospectionException e) {
//                            e.printStackTrace();
                            continue;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return t;
    }

    public static void release(Connection conn, Statement stat, ResultSet rs){
        try {
            if(rs!=null){
                rs.close();
            }
            if(stat!=null){
                stat.close();
            }
            if(conn!=null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

The above encapsulated tool classes are used in conjunction with DAO design patterns.

2.DAO Setup Mode

DAO(Database Access Object Database Access Object)

In order to reduce the coupling, the design mode of DAO encapsulation database operation is proposed.

It can separate business logic from database access. Relatively speaking, the database is relatively stable, in which DAO components rely on the database system to provide database access interface, isolating different database implementations.

Components of the DAO model

1 DAO interface (mainly adding modified query deletion method)

2 DAO Implementation Class

3 entity classes (domain), beans, entity, pojo, model)

PO (VO)(Persistent Object, Value Object)

VO (View Object)

DTO (Data Transfer Object)

Role: Used to transfer data through entity classes between data access code and business logic code

- Entity class characteristics:

private modification is commonly used for attributes

Provide public-modified getter/setter method

Entity classes provide parametric construction methods, and provide parametric construction according to business

Implementing java.io.Serializable interface and supporting serialization mechanism

4 Database Connection and Closing Tool Class

Design package name:

domain stores entity classes

Utls Storage Tool Class

dao storage interface

dao.impl stores implementation classes

Refer to the DAO pattern design case. https://blog.csdn.net/SjwFdb_1__1/article/details/100128177

3. Custom Implementing Connection Pool

Users need to get a connection to the database every time they request, and it usually takes a relatively large amount of resources and a long time to create a connection to the database. Assuming that the website has 100,000 visits a day, the database server needs to create 100,000 connections, which greatly wastes the resources of the database, and easily causes the memory overflow and extension of the database server.

Java provides a specification (interface) for connection pool implementation. Specification is written in Java. We need to implement DataSource interface!

The cases are as follows:

Note: There are many abstract methods in the DataSource interface. We just need to implement the getConnection method and then define ralease() to release resources and add connection objects from the new connection pool.

public class DbUtilsPool implements DataSource {

    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    private static List<Connection> connections = Collections.synchronizedList(new LinkedList<>());

    static{
        try {
            Properties prop = new Properties();
            InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties");
            prop.load(is);
            is.close();
            driver = prop.getProperty("driver");
            url = prop.getProperty("url");
            username = prop.getProperty("username");
            password = prop.getProperty("password");

            Class.forName(driver);
            for (int i = 0; i < 5; i++) {
                Connection conn = DriverManager.getConnection(url, username, password);
                connections.add(conn);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //Take the connection object from the connection pool, return the connection object in existence, return null in nonexistence
    @Override
    public Connection getConnection() throws SQLException {
        return connections.remove(0);
    }
    //Put the connection object back into the connection pool
    public static void release(Connection conn){
        connections.add(conn);
    }








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

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

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

    }

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

    }

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

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

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

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

Test code:

public class DbUtilsPoolTest {

    @Test
    public void testGetConn(){
        for (int i = 0; i < 8; i++) {
            DbUtilsPool myPool = new DbUtilsPool();
            Connection conn = null;
            try {
                conn = myPool.getConnection();
                System.out.println("Connect"+conn.hashCode()+"Success!");
                myPool.release(conn);
            } catch (Exception e) {
                System.out.println("Connection timeout, please reconnect......");
            }
        }
    }
}

Test results:

Duplicate connection objects are generated because there are five connection objects in the connection pool. When we need more than five connection objects, duplicate connection objects will be generated.

Topics: Database SQL Attribute Java