一、数据库连接池: 

  在一般用JDBC 进行连接数据库进行CRUD操作时,每一次都会:

    通过:java.sql.Connection conn = DriverManager.getConnection(url,user,password); 重新获取一个数据库的链接再进行操作,这样用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。

【总结】编写自己的JDBC框架
      
        所以为了减少服务器的压力,便可用连接池的方法:在启动Web应用时,数据就创建好一定数量的Connection链接
  存放到一个容器中,然后当用户请求时,服务器则向容器中获取Connection链接来处理用户的请求,当用户的请求完成后,
  又将该Connection 链接放回到该容器中。这样的一个容器称为连接池。

    【总结】编写自己的JDBC框架
  
  编写一个基本的连接池实现连接复用
       步骤:
       1、建立一个数据库连接池容器。(因为方便存取,则使用LinkedList集合)
       2、初始化一定数量的连接,放入到容器中。
       3、等待用户获取连接对象。(该部分要加锁)
          |---记得删除容器中对应的对象,放置别人同时获取到同一个对象。
       4、提供一个方法,回收用户用完的连接对象。
       5、要遵循先入先出的原则。

 1 import java.io.InputStream;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 import java.sql.SQLException;
 5 import java.util.LinkedList;
 6 import java.util.Properties;
 7 
 8 
 9 /**
10  * 一个基本的数据连接池:  
11  * 1、初始化时就建立一个容器,来存储一定数量的Connection 对象
12  * 2、用户通过调用MyDataSource 的getConnection 来获取Connection 对象。
13  * 3、再通过release 方法来回收Connection 对象,而不是直接关闭连接。
14  * 4、遵守先进先出的原则。
15  *  
16  *     
17  * @author 贺佐安
18  *
19  */
20 public class MyDataSource {
21     private static String url = null;
22     private static String password = null;
23     private static String user = null ;
24     private static String DriverClass = null;
25     private static LinkedList<Connection> pool = new LinkedList<Connection>() ;
26 //    注册数据库驱动
27     static {
28         try {
29             InputStream in = MyDataSource.class.getClassLoader()
30                     .getResourceAsStream("db.properties");
31             Properties prop = new Properties(); 
32             prop.load(in);
33             user = prop.getProperty("user"); 
34             url = prop.getProperty("url") ;
35             password = prop.getProperty("password") ; 
36             DriverClass = prop.getProperty("DriverClass") ;  
37             Class.forName(DriverClass) ;  
38             
39         } catch (Exception e) {
40             throw new RuntimeException(e) ;
41         }  
42     }
43     //初始化建立数据连接池
44     public MyDataSource ()  {
45         for(int i = 0 ; i < 10 ; i ++) {
46             try {
47                 Connection conn = DriverManager.getConnection(url, user, password) ;
48                 pool.add(conn) ;
49             } catch (SQLException e) {
50                 e.printStackTrace();
51             }
52         }
53     }
54     //、从连接池获取连接
55     public Connection getConnection() throws SQLException {
56         return pool.remove() ;
57     } 
58     // 回收连接对象。
59     public void release(Connection conn) {
60         System.out.println(conn+"被回收");
61         pool.addLast(conn) ;
62     } 
63     public int getLength() {
64         return pool.size() ;
65     }
66 }

  这样当我们要使用Connection 连接数据库时,则可以直接使用连接池中Connection 的对象。测试如下:

 1 import java.sql.Connection;
 2 import java.sql.SQLException;
 3 
 4 import org.junit.Test;
 5 
 6 
 7 public class MyDataSourceTest {
 8     
 9     
10     /**
11      * 获取数据库连接池中的所有连接。
12      */
13     @Test
14     public void Test() {
15         MyDataSource mds = new MyDataSource() ; 
16         Connection conn = null ;
17         try {
18             
19             for (int i = 0 ; i < 20 ; i ++) {
20                 conn = mds.getConnection() ;
21                 System.out.println(conn+"被获取;连接池还有:"+mds.getLength()); 
22                 mds.release(conn) ;
23             } 
24         } catch (SQLException e) {
25             e.printStackTrace();
26         } 
27     }
28 }

  再运行的时候,可以发现,循环10次后,又再一次获取到了第一次循环的得到的Connection对象。所以,这样可以大大的减轻数据库的压力。上面只是一个简单的数据库连接池,不完美的便是,回收需要调用数据池的release() 方法来进行回收,那么可以不可以直接调用Connection 实例的close 便完成Connection 对象的回收呢?

 


二、数据源:  

    > 编写连接池需实现javax.sql.DataSource接口。
      > 实现DataSource接口,并实现连接池功能的步骤:
        1、在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。

      2、实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。

    利用动态代理和包装设计模式来标准的数据源。

    1、包装设计模式实现标准数据源:

      这里的用包装设计模式,便是将Connection 接口进行包装。简单总结一下包装设计模式的步骤:

          a)定义一个类,实现与被包装类()相同的接口。
                |----可以先自己写一个适配器,然后后面继承这个适配器,改写需要改写的方法,提高编程效率。
             b)定义一个实例变量,记住被包装类的对象的引用。
             c)定义构造方法,转入被包装类的对象。

           e)对需要改写的方法,改写。
                    f)对不需要改写的方法,调用原来被包装类的对应方法。

      所以先编写一个类似适配器的类,将Connection 接口的方法都进行实现:

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.Map;
import java.util.Properties;


/**
 * 实现Connection 的适配器:
 * 目的:在使用包装设计模式时方便使用
 * @author 贺佐安
 *
 */

public class MyConnectionAdapter implements Connection {
    //用一个实例变量,记住被包装类的实例引用
    protected Connection conn ;  
    //构造函数,转入被包装类的对象
    public MyConnectionAdapter(Connection conn) {
        this.conn = conn ;
    }
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return conn.unwrap(iface);
    }
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return conn.isWrapperFor(iface);
    }
    @Override
    public Statement createStatement() throws SQLException {
        return conn.createStatement();
    }
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return conn.prepareStatement(sql);
    }
    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return conn.prepareCall(sql);
    }
    @Override
    public String nativeSQL(String sql) throws SQLException {
        return conn.nativeSQL(sql);
    }
    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        conn.setAutoCommit(autoCommit);
    }
    @Override
    public boolean getAutoCommit() throws SQLException {
        return conn.getAutoCommit();
    }
    @Override
    public void commit() throws SQLException {
        conn.commit() ;
    }
    @Override
    public void rollback() throws SQLException {
        conn.rollback() ;
    }
    @Override
    public void close() throws SQLException {
        conn.close() ;
    }
    @Override
    public boolean isClosed() throws SQLException {
        return conn.isClosed();
    }
    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return conn.getMetaData();
    }
    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        conn.setReadOnly(readOnly);
    }
    @Override
    public boolean isReadOnly() throws SQLException {
        return conn.isReadOnly();
    }
    @Override
    public void setCatalog(String catalog) throws SQLException {
        conn.setCatalog(catalog) ;
    }
    @Override
    public String getCatalog() throws SQLException {
        return conn.getCatalog();
    }
    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        conn.setTransactionIsolation(level) ;
    }
    @Override
    public int getTransactionIsolation() throws SQLException {
        return conn.getTransactionIsolation();
    }
    @Override
    public SQLWarning getWarnings() throws SQLException {
        return conn.getWarnings();
    }
    @Override
    public void clearWarnings() throws SQLException {
        conn.clearWarnings() ;
    }
    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency)
            throws SQLException {
        return conn.createStatement(resultSetType, resultSetConcurrency);
        
    }
    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType,
            int resultSetConcurrency) throws SQLException {
        return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
            int resultSetConcurrency) throws SQLException {
        return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
    }
    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return conn.getTypeMap();
    }
    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        conn.setTypeMap(map) ;
    }
    @Override
    public void setHoldability(int holdability) throws SQLException {
        conn.setHoldability(holdability) ;
    }
    @Override
    public int getHoldability() throws SQLException {
        return conn.getHoldability();
    }
    @Override
    public Savepoint setSavepoint() throws SQLException {
        return conn.setSavepoint();
    }
    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return conn.setSavepoint(name);
    }
    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        conn.rollback(savepoint);
    }
    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        conn.releaseSavepoint(savepoint);
    }
    @Override
    public Statement createStatement(int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }
    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
            int resultSetConcurrency, int resultSetHoldability)
            throws SQLException {
        return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }
    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
            throws SQLException {
        return conn.prepareStatement(sql, autoGeneratedKeys);
    }
    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
            throws SQLException {
        return conn.prepareStatement(sql, columnIndexes);
    }
    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames)
            throws SQLException {
        return conn.prepareStatement(sql, columnNames);
    }
    @Override
    public Clob createClob() throws SQLException {
        return conn.createClob();
    }
    @Override
    public Blob createBlob() throws SQLException {
        return conn.createBlob();
    }
    @Override
    public NClob createNClob() throws SQLException {
        return conn.createNClob();
    }
    @Override
    public SQLXML createSQLXML() throws SQLException {
        return conn.createSQLXML();
    }
    @Override
    public boolean isValid(int timeout) throws SQLException {
        return conn.isValid(timeout);
    }
    @Override
    public void setClientInfo(String name, String value)
            throws SQLClientInfoException {
        conn.setClientInfo(name, value) ;
    }
    @Override
    public void setClientInfo(Properties properties)
            throws SQLClientInfoException {
        conn.setClientInfo(properties) ;
    }
    @Override
    public String getClientInfo(String name) throws SQLException {
        return conn.getClientInfo(name);
    }
    @Override
    public Properties getClientInfo() throws SQLException {
        return conn.getClientInfo();
    }
    @Override
    public Array createArrayOf(String typeName, Object[] elements)
            throws SQLException {
        return conn.createArrayOf(typeName, elements);
    }
    @Override
    public Struct createStruct(String typeName, Object[] attributes)
            throws SQLException {
        return conn.createStruct(typeName, attributes);
    }
 
}
View Code

相关文章:

  • 2021-05-22
  • 2021-11-10
  • 2021-05-18
  • 2022-01-04
  • 2021-11-20
  • 2021-10-01
猜你喜欢
  • 2022-01-15
  • 2021-05-21
  • 2021-06-29
  • 2022-12-23
  • 2021-10-18
  • 2021-10-18
相关资源
相似解决方案