• 数据库连接池


    数据库连接池

    • 数据库的连接对象创建工作,比较消耗性能
    • 在开始的时候在内存中开辟一块空间(集合、池子),一开始先往池子里放置多个连接对象
    • 以后需要连接对象时,直接从池子中取,不需要再自己去创建对象了
    • 使用完毕,将连接归还给池子,保证连接对象可以循环利用

    自定义数据库连接池

    代码实现

     1 public class MyDataSource implements DataSource {
     2     
     3     private List<Connection> list = new ArrayList<Connection>();
     4 
     5     public MyDataSource() {
     6         for (int i = 0; i < 10; i++) {
     7             Connection conn = DBUtils.getConn();
     8             list.add(conn);
     9         }
    10     }
    11 
    12     @Override
    13     public Connection getConnection() throws SQLException {
    14         if (list.size() == 0) {
    15             for (int i = 0; i < 5; i++) {
    16                 Connection conn = DBUtils.getConn();
    17                 list.add(conn);
    18             }
    19         }
    20         
    21         Connection conn = list.remove(0);
    22         return conn;
    23     }
    24     
    25     public void addBack(Connection conn) {
    26         list.add(conn);
    27     }
    28     
    29     @Override
    30     public PrintWriter getLogWriter() throws SQLException {
    31         // TODO Auto-generated method stub
    32         return null;
    33     }
    34 
    35     @Override
    36     public void setLogWriter(PrintWriter out) throws SQLException {
    37         // TODO Auto-generated method stub
    38 
    39     }
    40 
    41     @Override
    42     public void setLoginTimeout(int seconds) throws SQLException {
    43         // TODO Auto-generated method stub
    44 
    45     }
    46 
    47     @Override
    48     public int getLoginTimeout() throws SQLException {
    49         // TODO Auto-generated method stub
    50         return 0;
    51     }
    52 
    53     @Override
    54     public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    55         // TODO Auto-generated method stub
    56         return null;
    57     }
    58 
    59     @Override
    60     public <T> T unwrap(Class<T> iface) throws SQLException {
    61         // TODO Auto-generated method stub
    62         return null;
    63     }
    64 
    65     @Override
    66     public boolean isWrapperFor(Class<?> iface) throws SQLException {
    67         // TODO Auto-generated method stub
    68         return false;
    69     }
    70 
    71     @Override
    72     public Connection getConnection(String username, String password) throws SQLException {
    73         // TODO Auto-generated method stub
    74         return null;
    75     }
    76 
    77 }
     1 public class TestDemo {
     2     @Test
     3     public void test() {
     4         Connection conn = null;
     5         PreparedStatement ps = null;
     6         MyDataSource dataSource = new MyDataSource();
     7         try {
     8             conn = dataSource.getConnection();
     9             String sql = "select * from person";
    10             ps = conn.prepareStatement(sql);
    11             ResultSet resultSet = ps.executeQuery();
    12             while (resultSet.next()) {
    13                 String name = resultSet.getString(2);
    14                 System.out.println(name);
    15             }
    16         } catch (SQLException e) {
    17             e.printStackTrace();
    18         } finally {
    19             try {
    20                 if(ps!=null) {
    21                     ps.close();
    22                 }
    23             } catch (SQLException e) {
    24                 e.printStackTrace();
    25             }
    26             dataSource.addBack(conn);
    27         }
    28     }
    29 }

    出现的问题

    1. 需要额外记住 addBack方法

    2. 单例

    3. 无法面向接口编程

      使用DataSource dataSource = new MyDataSource();代替代码中的MyDataSource dataSource = new MyDataSource();finall块中的dataSource.addback(conn);会抛出异常

      因为接口里面没有定义addBack方法(编译看左边,运行看右边)

    怎么解决? 以addBack 为切入点

    由于多了一个addBack 方法,所以使用这个连接池的地方,需要额外记住这个方法,并且还不能面向接口编程

      我们打算修改接口中的那个close方法。 原来的Connection对象的close方法,是真的关闭连接。 打算修改这个close方法,以后在调用close, 并不是真的关闭,而是归还连接对象

    如何扩展Connection中的close方法

    1. 直接改源码,无法实现
    2. 继承,必须知道这个接口的具体实现,但是Connection接口的具体实现类找不到
    3. 使用装饰者模式,可以

    使用装饰者模式自定义数据库连接池

    包装类

      1 public class ConnectionWrap implements Connection{
      2     private Connection conn;
      3     private List<Connection> list;
      4 
      5     public ConnectionWrap(Connection conn, List<Connection> list) {
      6         super();
      7         this.conn = conn;
      8         this.list = list;
      9     }
     10 
     11     @Override
     12     public void close() throws SQLException {
     13         System.out.println("连接归还前,连接池中连接数:"+list.size());
     14         list.add(conn);
     15         System.out.println("连接归还后,连接池中连接数:"+list.size());
     16     }
     17 
     18     @Override
     19     public PreparedStatement prepareStatement(String sql) throws SQLException {
     20         return conn.prepareStatement(sql);
     21     }
     22 
     23     @Override
     24     public <T> T unwrap(Class<T> iface) throws SQLException {
     25         // TODO Auto-generated method stub
     26         return null;
     27     }
     28 
     29     @Override
     30     public boolean isWrapperFor(Class<?> iface) throws SQLException {
     31         // TODO Auto-generated method stub
     32         return false;
     33     }
     34 
     35     @Override
     36     public Statement createStatement() throws SQLException {
     37         // TODO Auto-generated method stub
     38         return null;
     39     }
     40 
     41     @Override
     42     public CallableStatement prepareCall(String sql) throws SQLException {
     43         // TODO Auto-generated method stub
     44         return null;
     45     }
     46 
     47     @Override
     48     public String nativeSQL(String sql) throws SQLException {
     49         // TODO Auto-generated method stub
     50         return null;
     51     }
     52 
     53     @Override
     54     public void setAutoCommit(boolean autoCommit) throws SQLException {
     55         // TODO Auto-generated method stub
     56         
     57     }
     58 
     59     @Override
     60     public boolean getAutoCommit() throws SQLException {
     61         // TODO Auto-generated method stub
     62         return false;
     63     }
     64 
     65     @Override
     66     public void commit() throws SQLException {
     67         // TODO Auto-generated method stub
     68         
     69     }
     70 
     71     @Override
     72     public void rollback() throws SQLException {
     73         // TODO Auto-generated method stub
     74         
     75     }
     76 
     77     @Override
     78     public boolean isClosed() throws SQLException {
     79         // TODO Auto-generated method stub
     80         return false;
     81     }
     82 
     83     @Override
     84     public DatabaseMetaData getMetaData() throws SQLException {
     85         // TODO Auto-generated method stub
     86         return null;
     87     }
     88 
     89     @Override
     90     public void setReadOnly(boolean readOnly) throws SQLException {
     91         // TODO Auto-generated method stub
     92         
     93     }
     94 
     95     @Override
     96     public boolean isReadOnly() throws SQLException {
     97         // TODO Auto-generated method stub
     98         return false;
     99     }
    100 
    101     @Override
    102     public void setCatalog(String catalog) throws SQLException {
    103         // TODO Auto-generated method stub
    104         
    105     }
    106 
    107     @Override
    108     public String getCatalog() throws SQLException {
    109         // TODO Auto-generated method stub
    110         return null;
    111     }
    112 
    113     @Override
    114     public void setTransactionIsolation(int level) throws SQLException {
    115         // TODO Auto-generated method stub
    116         
    117     }
    118 
    119     @Override
    120     public int getTransactionIsolation() throws SQLException {
    121         // TODO Auto-generated method stub
    122         return 0;
    123     }
    124 
    125     @Override
    126     public SQLWarning getWarnings() throws SQLException {
    127         // TODO Auto-generated method stub
    128         return null;
    129     }
    130 
    131     @Override
    132     public void clearWarnings() throws SQLException {
    133         // TODO Auto-generated method stub
    134         
    135     }
    136 
    137     @Override
    138     public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    139         // TODO Auto-generated method stub
    140         return null;
    141     }
    142 
    143     @Override
    144     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
    145             throws SQLException {
    146         // TODO Auto-generated method stub
    147         return null;
    148     }
    149 
    150     @Override
    151     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    152         // TODO Auto-generated method stub
    153         return null;
    154     }
    155 
    156     @Override
    157     public Map<String, Class<?>> getTypeMap() throws SQLException {
    158         // TODO Auto-generated method stub
    159         return null;
    160     }
    161 
    162     @Override
    163     public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
    164         // TODO Auto-generated method stub
    165         
    166     }
    167 
    168     @Override
    169     public void setHoldability(int holdability) throws SQLException {
    170         // TODO Auto-generated method stub
    171         
    172     }
    173 
    174     @Override
    175     public int getHoldability() throws SQLException {
    176         // TODO Auto-generated method stub
    177         return 0;
    178     }
    179 
    180     @Override
    181     public Savepoint setSavepoint() throws SQLException {
    182         // TODO Auto-generated method stub
    183         return null;
    184     }
    185 
    186     @Override
    187     public Savepoint setSavepoint(String name) throws SQLException {
    188         // TODO Auto-generated method stub
    189         return null;
    190     }
    191 
    192     @Override
    193     public void rollback(Savepoint savepoint) throws SQLException {
    194         // TODO Auto-generated method stub
    195         
    196     }
    197 
    198     @Override
    199     public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    200         // TODO Auto-generated method stub
    201         
    202     }
    203 
    204     @Override
    205     public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
    206             throws SQLException {
    207         // TODO Auto-generated method stub
    208         return null;
    209     }
    210 
    211     @Override
    212     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
    213             int resultSetHoldability) throws SQLException {
    214         // TODO Auto-generated method stub
    215         return null;
    216     }
    217 
    218     @Override
    219     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
    220             int resultSetHoldability) throws SQLException {
    221         // TODO Auto-generated method stub
    222         return null;
    223     }
    224 
    225     @Override
    226     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    227         // TODO Auto-generated method stub
    228         return null;
    229     }
    230 
    231     @Override
    232     public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
    233         // TODO Auto-generated method stub
    234         return null;
    235     }
    236 
    237     @Override
    238     public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
    239         // TODO Auto-generated method stub
    240         return null;
    241     }
    242 
    243     @Override
    244     public Clob createClob() throws SQLException {
    245         // TODO Auto-generated method stub
    246         return null;
    247     }
    248 
    249     @Override
    250     public Blob createBlob() throws SQLException {
    251         // TODO Auto-generated method stub
    252         return null;
    253     }
    254 
    255     @Override
    256     public NClob createNClob() throws SQLException {
    257         // TODO Auto-generated method stub
    258         return null;
    259     }
    260 
    261     @Override
    262     public SQLXML createSQLXML() throws SQLException {
    263         // TODO Auto-generated method stub
    264         return null;
    265     }
    266 
    267     @Override
    268     public boolean isValid(int timeout) throws SQLException {
    269         // TODO Auto-generated method stub
    270         return false;
    271     }
    272 
    273     @Override
    274     public void setClientInfo(String name, String value) throws SQLClientInfoException {
    275         // TODO Auto-generated method stub
    276         
    277     }
    278 
    279     @Override
    280     public void setClientInfo(Properties properties) throws SQLClientInfoException {
    281         // TODO Auto-generated method stub
    282         
    283     }
    284 
    285     @Override
    286     public String getClientInfo(String name) throws SQLException {
    287         // TODO Auto-generated method stub
    288         return null;
    289     }
    290 
    291     @Override
    292     public Properties getClientInfo() throws SQLException {
    293         // TODO Auto-generated method stub
    294         return null;
    295     }
    296 
    297     @Override
    298     public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
    299         // TODO Auto-generated method stub
    300         return null;
    301     }
    302 
    303     @Override
    304     public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
    305         // TODO Auto-generated method stub
    306         return null;
    307     }
    308 
    309     @Override
    310     public void setSchema(String schema) throws SQLException {
    311         // TODO Auto-generated method stub
    312         
    313     }
    314 
    315     @Override
    316     public String getSchema() throws SQLException {
    317         // TODO Auto-generated method stub
    318         return null;
    319     }
    320 
    321     @Override
    322     public void abort(Executor executor) throws SQLException {
    323         // TODO Auto-generated method stub
    324         
    325     }
    326 
    327     @Override
    328     public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
    329         // TODO Auto-generated method stub
    330         
    331     }
    332 
    333     @Override
    334     public int getNetworkTimeout() throws SQLException {
    335         // TODO Auto-generated method stub
    336         return 0;
    337     }
    338     
    339 }
    View Code

    自定义数据库连接池

    public class MyDataSource implements DataSource {
        
        private List<Connection> list = new ArrayList<Connection>();
    
        public MyDataSource() {
            for (int i = 0; i < 10; i++) {
                Connection conn = DBUtils.getConn();
                list.add(conn);
            }
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            if (list.size() == 0) {
                for (int i = 0; i < 5; i++) {
                    Connection conn = DBUtils.getConn();
                    list.add(conn);
                }
            }
            Connection conn = list.remove(0);
            //使用Connection的包装类
            ConnectionWrap connWrap = new ConnectionWrap(conn, list);
            return connWrap;
        }
        
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            // TODO Auto-generated method stub
            return null;
        }
    }

    测试类

    public class TestDemo {
        @Test
        public void test() {
            Connection conn = null;
            PreparedStatement ps = null;
            MyDataSource dataSource = new MyDataSource();
            ResultSet resultSet = null;
            try {
                conn = dataSource.getConnection();
                String sql = "select * from person";
                ps = conn.prepareStatement(sql);
                resultSet = ps.executeQuery();
                while (resultSet.next()) {
                    String name = resultSet.getString(2);
                    System.out.println(name);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtils.releaseResource(resultSet, ps, conn);
            }
        }
    }

    控制台输出

    smile
    wxf
    admin
    qf
    wxf_1
    连接归还前,连接池中连接数:9
    连接归还后,连接池中连接数:10

    开源连接池

    • DBCP
    • C3P0(常用)

    DBCP

    导入相关jar(commons-dbcp-*.jar、commons-pool-*.jar、mysql-connector-java-*-bin.jar)

    dbcpconfig.properties

    #连接设置
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test
    username=root
    password=root
    
    #<!-- 初始化连接 -->
    initialSize=10
    
    #最大连接数量
    maxActive=50
    
    #<!-- 最大空闲连接 -->
    maxIdle=20
    
    #<!-- 最小空闲连接 -->
    minIdle=5
    
    #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
    maxWait=60000
    
    #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
    #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
    connectionProperties=useUnicode=true;characterEncoding=gbk
    
    #指定由连接池所创建的连接的自动提交(auto-commit)状态。
    defaultAutoCommit=true
    
    #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
    #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
    defaultTransactionIsolation=READ_UNCOMMITTED

    TestDBCP.java 

     1 public class TestDBCP {
     2 
     3     @Test
     4     public void test() {
     5         /*BasicDataSource dataSource = new BasicDataSource();
     6         dataSource.setUrl("jdbc:mysql://localhost:3306/test");
     7         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
     8         dataSource.setUsername("root");
     9         dataSource.setPassword("root");*/
    10         BasicDataSourceFactory factory = new BasicDataSourceFactory();
    11         DataSource dataSource = null;
    12         
    13         Connection conn = null;
    14         PreparedStatement ps = null;
    15         try {
    16             Properties prop = new Properties();
    17             InputStream inStream = new FileInputStream("src/dbcpconfig.properties");
    18             prop.load(inStream);
    19             dataSource = factory.createDataSource(prop);
    20             
    21             
    22             conn = dataSource.getConnection();
    23             String sql = "insert into person values(null,?,?,?,null)";
    24             ps = conn.prepareStatement(sql);
    25             ps.setString(1, "admin");
    26             ps.setInt(2, 24);
    27             ps.setDate(3, new Date(0));
    28             int result = ps.executeUpdate();
    29             if(result>0) {
    30                 System.out.println("操作成功!!!");
    31             }else {
    32                 System.out.println("操作失败!!!");
    33             }
    34         } catch (SQLException e) {
    35             e.printStackTrace();
    36         } catch (Exception e) {
    37             e.printStackTrace();
    38         } finally {
    39             try {
    40                 if (conn != null) {
    41                     conn.close();
    42                 }
    43                 if(ps != null) {
    44                     ps.close();
    45                 }
    46             } catch (SQLException e) {
    47                 e.printStackTrace();
    48             }
    49         }
    50     }
    51 }

    控制台输出

    操作成功!!!

    C3P0

    使用代码方式

    导入jar(c3p0-0.9.1.2-jdk1.3.jar、c3p0-0.9.1.2.jar、c3p0-oracle-thin-extras-0.9.1.2.jar

    TestC3P0.java

     1 public class TestC3P0 {
     2 
     3     @Test
     4     public void test() {
     5         Connection conn = null;
     6         PreparedStatement ps = null;
     7         //1.创建dataSource
     8         ComboPooledDataSource dataSource = new ComboPooledDataSource();
     9         
    10         try {
    11             //2.设置连接数据库属性
    12             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    13             dataSource.setDriverClass("com.mysql.jdbc.Driver");
    14             dataSource.setUser("root");
    15             dataSource.setPassword("root");
    16             //3.获取连接
    17             conn = dataSource.getConnection();
    18             
    19             //4.操作
    20             String sql = "insert into person values(null,?,?,?,null)";
    21             ps = conn.prepareStatement(sql);
    22             ps.setString(1, "admin");
    23             ps.setInt(2, 24);
    24             ps.setDate(3, new Date(0));
    25             int result = ps.executeUpdate();
    26             if(result>0) {
    27                 System.out.println("操作成功!!!");
    28             }else {
    29                 System.out.println("操作失败!!!");
    30             }
    31         } catch (PropertyVetoException e) {
    32             e.printStackTrace();
    33         } catch (SQLException e) {
    34             e.printStackTrace();
    35         } finally {
    36             try {
    37                 if (conn != null) {
    38                     conn.close();
    39                 }
    40                 if(ps != null) {
    41                     ps.close();
    42                 }
    43             } catch (SQLException e) {
    44                 e.printStackTrace();
    45             }
    46         }
    47     }
    48 }

    控制台输出

    操作成功!!!

    使用配置文件方式

    c3p0-config.xml(文件名必须是这个,不能写错

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
      <default-config>
        <property name="automaticTestTable">con_test</property>
        <property name="checkoutTimeout">30000</property>
        <property name="idleConnectionTestPeriod">30</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
        
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
        <property name="user">root</property>
        <property name="password">root</property>
      </default-config>
    
      <!-- This app is massive! -->
      <named-config name="oracle"> 
        <property name="acquireIncrement">50</property>
        <property name="initialPoolSize">100</property>
        <property name="minPoolSize">50</property>
        <property name="maxPoolSize">1000</property>
        <!-- intergalactoApp adopts a different approach to configuring statement caching -->
        <property name="maxStatements">0</property> 
        <property name="maxStatementsPerConnection">5</property>
      </named-config>
    </c3p0-config>
    • name-config标签中可以配置连接其他的数据库,如Oracle,sqlserver等
    • new ComboPooledDataSource("oracle"),就会找name是oracle的name-config

    TestC3P0.java

     1 public class TestC3P0 {
     2 
     3     @Test
     4     public void test() {
     5         Connection conn = null;
     6         PreparedStatement ps = null;
     7         //1.创建dataSource(类加载器自动加载c3p0-config.xml文件,默认找default-config标签下的配置),
     8         ComboPooledDataSource dataSource = new ComboPooledDataSource();
     9         
    10         try {
    11             //2.设置连接数据库属性
    12             /*dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    13             dataSource.setDriverClass("com.mysql.jdbc.Driver");
    14             dataSource.setUser("root");
    15             dataSource.setPassword("root");*/
    16             //3.获取连接
    17             conn = dataSource.getConnection();
    18             
    19             //4.操作
    20             String sql = "insert into person values(null,?,?,?,null)";
    21             ps = conn.prepareStatement(sql);
    22             ps.setString(1, "admin");
    23             ps.setInt(2, 24);
    24             ps.setDate(3, new Date(0));
    25             int result = ps.executeUpdate();
    26             if(result>0) {
    27                 System.out.println("操作成功!!!");
    28             }else {
    29                 System.out.println("操作失败!!!");
    30             }
    31         } catch (SQLException e) {
    32             e.printStackTrace();
    33         } finally {
    34             try {
    35                 if (conn != null) {
    36                     conn.close();
    37                 }
    38                 if(ps != null) {
    39                     ps.close();
    40                 }
    41             } catch (SQLException e) {
    42                 e.printStackTrace();
    43             }
    44         }
    45     }
    46 }

    控制台输出

    操作成功!!!
  • 相关阅读:
    MWC飞控增加声纳定高的方法(转)
    c语言字符串分割函数(转)
    移动端IM系统的协议选型:UDP还是TCP?(转)
    如何编写Linux设备驱动程序(转)
    TCP连接探测中的Keepalive和心跳包(转)
    为什么说基于TCP的移动端IM仍然需要心跳保活?(转)
    基于 FPGA 的图像边缘检测(转)
    NTC热敏电阻基础以及应用和选择(转)
    通用CRC32校验程序,可完美匹配STM32硬件CRC算法(转)
    MAX31855 热电偶至数字输出转换器
  • 原文地址:https://www.cnblogs.com/qf123/p/10097662.html
Copyright © 2020-2023  润新知