1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        c3p0 數(shù)據(jù)庫連接池如何正確地關(guān)閉資源?

        共 10234字,需瀏覽 21分鐘

         ·

        2021-03-08 01:53

        公眾號(hào)關(guān)注 “GitHub今日熱榜
        設(shè)為 “星標(biāo)”,帶你挖掘更多開發(fā)神器!






        一.問題分析


        關(guān)于c3p0數(shù)據(jù)庫連接池的資源的關(guān)閉是一個(gè)很重要的問題,但是資源的關(guān)閉不僅僅是只調(diào)用close()方法,將鏈接放入池中那么簡單,如果你不考慮數(shù)據(jù)源DataSource的關(guān)閉,那么你的Demo將在很少的數(shù)據(jù)庫交互之后報(bào)出“too many connections”。下面先看這樣一些代碼(注:測(cè)試程序我也就不按照正確的開發(fā)模式寫代碼了):


        CreateConnection.java(本文討論的重點(diǎn)在這里)


        public class CreateConnection {
            private ComboPooledDataSource dataSource=new ComboPooledDataSource("mysql");
            public Connection getConnection(){
                Connection conn=null;
                try {
                    conn=dataSource.getConnection();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return conn;
            }
         
            public DataSource getDataSource() {
                return dataSource;
            }
            public void closeConn(Connection conn){
                try {
                    if(conn!=null && conn.isClosed()){
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }


        testDao.java


        public class testDao {
            public int reginster (String username,String pwd){
                CreateConnection c=new CreateConnection();
                Connection conn=c.getConnection();
                int i=0;
                String sql="insert into user(username,pwd)values(?,?)";
                try {
                    PreparedStatement ps = conn.prepareStatement(sql);
                    ps.setString(1,username);
                    ps.setString(2,pwd);
                    i=ps.executeUpdate();
                }catch (Exception ex){
                    ex.printStackTrace();
                }finally{
                    try {
                        c.closeConn(conn);
                    }catch (Exception ex){
                        ex.printStackTrace();}
                }
                return i;
            }
        }


        testServlet.java


        public class testServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                 String username=request.getParameter("username");
                 String pwd=request.getParameter("pwd");
                 testDao td=new testDao();
                 response.setCharacterEncoding("utf-8");
                 response.setContentType("text/html;charset=utf-8");
                int i=td.reginster(username,pwd);
                if(i==1){
                    System.out.println("------------------------test");
                    response.getWriter().print("<script language='javascript'>alert('注冊(cè)成功?。?!');history.back(-1)</script>");
                }else{
                    response.getWriter().print("<script language='javascript'>alert('注冊(cè)失?。。?!');history.back(-1)</script>");
                }
            }
         
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                   doPost(request,response);
            }
        }


        login.jsp


        <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
        <html>
        <head>
            <title>注冊(cè)</title>
        </head>
        <body>
        <form action="bluemsun/testServlet" method="post">
           用戶名:<input type="text" name="username"/><br>
         
            密碼:<input type="password" name="pwd"/>
            <input type="submit" value="注冊(cè)"/>
        </form>
        </body>
        </html>


        上邊程序在進(jìn)行多次交互之后會(huì)報(bào)出“too many connections”的錯(cuò)誤,原因分析如下:原因就在于程序只將鏈接放回了鏈接池使其處于空閑狀態(tài),但是卻沒有關(guān)閉dataSource , 這就導(dǎo)致目前dataSource中的初始化鏈接一直處于鏈接池中,當(dāng)下一次交互開始后又重新創(chuàng)建了新的dataSource,而下一次的dataSource還是不能被關(guān)閉,就這樣每次都會(huì)累積不能被重用的鏈接,假如在配置時(shí)連接池的初始鏈接至配置數(shù)時(shí)100,而數(shù)據(jù)庫的最大鏈接數(shù)是1000,那么在經(jīng)過10次交互后會(huì)出現(xiàn)“too many connections”的錯(cuò)誤。然而當(dāng)把資源關(guān)閉的方法修改成如下的方法時(shí)就會(huì)發(fā)現(xiàn)永遠(yuǎn)不會(huì)報(bào)出”too many connections”的錯(cuò)誤:


        public void closeConn(Connection conn){
                try {
                    if(conn!=null && conn.isClosed()){
                        conn.close();
                    }
                  datasource.close();
                 } catch (SQLException e) {
                    e.printStackTrace();
                 }
            }
         datasource.close();
                 } catch (SQLException e) {
                    e.printStackTrace();
                 }
            }


        上邊貼出來的方法時(shí)將DataSource也進(jìn)行了關(guān)閉。


        二.方法改進(jìn)


        通過上邊的分析,我們基本知道了問題出現(xiàn)的原因了,接下來就是改進(jìn)連接池的使用了,先貼一下改進(jìn)的代碼:


        public class C3P0Util {
           private static DataSource dataSource=null;
              static{
                  dataSource=new ComboPooledDataSource("mysql1");
              }
                
              /**
               * 獲取數(shù)據(jù)庫連接
               * @return
               */
          
              public static Connection getConnection(){
                  Connection conn=null;
                  try {
                       conn=dataSource.getConnection();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
                  return conn;
              }
            
              public static DataSource getDataSource() {
                  return dataSource;
              }
              /**
               *
               * @param conn
               */
          
              public static void closeConn(Connection conn){
                  try {
                      if(conn!=null && conn.isClosed()){
                          conn.close();
                      }
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
        }


        從上邊程序中我們可以看出,是把所有的資源都用static描述,也就是把所有資源都交給了類,這樣做的好處是,每次交互都是共享C3P0Util類的datasource資源,不需要每次創(chuàng)建和關(guān)閉datasource資源,真正體現(xiàn)出了鏈接池的‘池’的特性。



        出處:csdn.net/qq_40400960/article/details/80446572








        關(guān)注GitHub今日熱榜,專注挖掘好用的開發(fā)工具,致力于分享優(yōu)質(zhì)高效的工具、資源、插件等,助力開發(fā)者成長!







        點(diǎn)個(gè)在看 你最好看









        瀏覽 63
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黄色工厂这里只有精品 | 伊人天天干 | 精品一区二区在线播放 | 亚洲人成色777777 | 成人AV影视 | 少妇性色婬片AAA直播 | 曰韩欧美一级 | 天天日天天操天天 | 亚洲成人视屏 | 少屄视频观看 |