3. 使用装饰者设计模式创建数据库连接池

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3. 使用装饰者设计模式创建数据库连接池相关的知识,希望对你有一定的参考价值。

装饰者设计模式

如果想要对某个对象的功能进行扩展时,就可以使用装饰者设计模式。

装饰者设计模式的使用方式:

  1. 编写一个类,实现与被包装类相同的接口。【就是说和你新建的装饰类要模仿别的一样 这里指的是 实现Connction接口 就模仿了JDBC的Connction接口.
  2. 定义一个被包装类类型的变量。
  3. 定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
  4. 对于不需要改写的方法,调用原有的方法。
  5. 对于需要改写的方法,写自己的代码。

目前的问题在于我们不希望Connection对象中的close方法关闭连接,而是希望去将连接返回到池中这时就需要对Connection类进行包装因为我们使用的mysql数据库,所以这里面实际上是对com.mysql.jdbc.Connection的包装。根据上面的方式,来包装一下Connection类。

全代码: Util > DB.java:

package Util;

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

public class DB {
    private static String url = "jdbc:mysql://localhost:3306/jdbc";
    private static String user = "root";
    private static String pass = "root";

    static {
        // 连接数据库
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection GetConnction() {
        try {
            return DriverManager.getConnection(url, user, pass);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}
package Util;

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

public class DB {
    private static String url = "jdbc:mysql://localhost:3306/jdbc";
    private static String user = "root";
    private static String pass = "root";

    static {
        // 连接数据库
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection GetConnction() {
        try {
            return DriverManager.getConnection(url, user, pass);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

 

然后我们包装一个自己的 Connction 主要重写Close方法:

MyCloseConnection > MyConntion.java:

package MyCloseConnection;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class MyConntion implements Connection{
    
    private Connection mConn = null;
    private LinkedList<Connection> mPool = null;
    
    /***
     * 构造函数
     * @param mConn
     * @param mPool
     */
    public MyConntion(Connection mConn, LinkedList<Connection> mPool) {
        this.mConn = mConn;
        this.mPool = mPool;
    }
    
    
    
    


/*----------------------------------------------------*/
    
    //主要还得重写这个Close!!
    @Override
    public void close() throws SQLException {
        this.mPool.add(mConn);    //使用完 放回去
    }

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

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

    @Override
    public void abort(Executor executor) throws SQLException {

    }

    @Override
    public void clearWarnings() throws SQLException {

    }


    @Override
    public void commit() throws SQLException {

    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    @Override
    public void rollback() throws SQLException {

    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {

    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {

    }

    @Override
    public void setCatalog(String catalog) throws SQLException {

    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {

    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {

    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {

    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {

    }

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

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

    @Override
    public void setSchema(String schema) throws SQLException {

    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {

    }

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

}

后面的代码用不到的你别去写即可。

 

然后我们新建一个连接池【规范的】:

ConnPool > Connpool.java

主要重写GetConntion 方法 ,返回的是自己包装过的【改写过Close的】, 那么就很完美了。

package ConnPool;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import MyCloseConnection.MyConntion;
import Util.DB;

public class Connpool implements DataSource{
    
    private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>());
    
    static {
        //创建连接池 顺便解决线程不安全
        for(int i = 0;i < 10;i++) {
            Connection conn = DB.GetConnction();
            if(conn != null) {
                pool.add(conn);
            }
        }
        //是否成功添加
        System.out.println("数据库连接池初始化成功:" + pool.size() + "个");
    }
    
    /*------------------------------------------------------------------------*/

    //主要重写这个GetConnection【无参的】 关键看这里! 因为取出是最关键的!
    @Override
    public Connection getConnection() throws SQLException {
        
        if(pool.size() > 0) {
            //在池中取出一个连接
            Connection conn = pool.removeFirst();
            //放入自己包装过的 Conntion中【这个包装过的 也是一个Connection ! 记住啊】
            MyConntion myConntion = new MyConntion(conn, pool);
            
            //返回我包装过的‘Connection’
            return myConntion;
            
        }else {
            throw new ExceptionInInitializerError("服务器繁忙,请稍后重试");
        }
    }

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

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

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

    @Override
    public void setLogWriter(PrintWriter arg0) throws SQLException {
    }

    @Override
    public void setLoginTimeout(int arg0) throws SQLException {
    }

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

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



}

 

注意: 上面的代码会报错 ,但是不是为了去实现它 而是学它的原理

嫌代码多的可 使用适配器模式创建 。

至于为什么报错 以后会了再说,现在主要是懂思想即可,后面直接用第三方的连接池.

 

以上是关于3. 使用装饰者设计模式创建数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

自定义连接池(装饰者模式)

设计模式之装饰者模式

day07 c3p0连接池

JDBC(连接池) -- 02(II)

连接池

浅析设计模式3 —— 装饰者模式