java - 整个代码中未正确使用数据库连接池

标签 java database-connection datasource connection-pooling

我正在处理遗留代码,由于我们有主要的数据库连接问题(始终有 1000 多个 sleep 连接)和如此缓慢的返回结果,我决定研究我们所谓的“Database Pooling' 架构紧密结合。

显然我们有两个Database.java和2个ConnectionPool.java,一对在Web应用程序模块中,另一对在数据库模块中。

所以它看起来像这样:

package mil.dlas.database;

  Database.java
  ConnectionPool.java

package ti.dlas;
  Database.java
  ConnectionPool.java

包 ti.dlas

public synchronized void getConn(ErrorBean myError)
{
    try
    {
        try
        {
            if (this.webBasedConnection)
            {
                if(dataSource == null)
                {
                    dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb");
                }

                if(dataSource == null)
                {
                    dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb");
                }

                conn = dataSource.getConnection();
            }
            else
            {
                getConnInterfaceBased(myError);
            }
        }
        catch (NamingException e)
        {
            e.printStackTrace();
            getConnInterfaceBased(myError);
        }
        catch(SQLException e)
        {
            e.printStackTrace();
            getConnInterfaceBased(myError);
        }
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
        getConnInterfaceBased(myError);
    }
}
public synchronized void insertOrUpdatePS(String query,Object[] param, ErrorBean eb)
{
        java.sql.PreparedStatement pStat = null;
        try
        {          
            getConn(eb);
            pStat = conn.prepareStatement(query);

            for(int i=0; i<param.length;i++)
            {
                pStat.setObject(i+1,param[i]);
            }
            iRowsUpdated = pStat.executeUpdate();
        }
        catch(SQLException e)
        {e.printStackTrace();}
        catch(Exception e)
        {e.printStackTrace();}
        finally {
            if(pStat!=null)            
                try {pStat.close();}
                catch(SQLException e){}            
            returnConn();
        }
}
/**ConnectionPool .java**/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

public class ConnectionPool implements Runnable, java.io.Serializable{
  private String driver, url, username, password;
  private int maxConnections;
  private boolean waitIfBusy;
  private Vector availableConnections, busyConnections;
  private boolean connectionPending = false;

  public ConnectionPool(String driver, String url,
                        String username, String password,
                        int initialConnections,
                        int maxConnections,
                        boolean waitIfBusy)
      throws SQLException {
    this.driver = driver;
    this.url = url;
    this.username = username;
    this.password = password;
    this.maxConnections = maxConnections;
    this.waitIfBusy = waitIfBusy;
    if (initialConnections > maxConnections) {
      initialConnections = maxConnections;
    }
    availableConnections = new Vector(initialConnections);
    busyConnections = new Vector();
    for(int i=0; i<initialConnections; i++) {
      availableConnections.addElement(makeNewConnection());
    }
  }

  public synchronized Connection getConnection()
      throws SQLException {
    if (!availableConnections.isEmpty()) {
      Connection existingConnection =
        (Connection)availableConnections.lastElement();
      int lastIndex = availableConnections.size() - 1;
      availableConnections.removeElementAt(lastIndex);

      if (existingConnection.isClosed()) {
        notifyAll(); 
        return(getConnection());
      } else {
        busyConnections.addElement(existingConnection);
        return(existingConnection);
      }
    } else {
      if ((totalConnections() < maxConnections) &&
          !connectionPending) {
        makeBackgroundConnection();
      } else if (!waitIfBusy) {
        throw new SQLException("Connection limit reached");
      }

      try {
        wait();
      } catch(InterruptedException ie) {}
      return(getConnection());
    }
  }

  private void makeBackgroundConnection() {
    connectionPending = true;
    try {
      Thread connectThread = new Thread(this);
      connectThread.start();
    } catch(OutOfMemoryError oome) {}
  }

  public void run() {
    try {
      Connection connection = makeNewConnection();
      synchronized(this) {
        availableConnections.addElement(connection);
        connectionPending = false;
        notifyAll();
      }
    } catch(Exception e) { }
  }

  private Connection makeNewConnection()
      throws SQLException {
    try {
        Class.forName(driver);
      Connection connection =
        DriverManager.getConnection(url, username, password);
      return(connection);
    } catch(ClassNotFoundException cnfe) {
      throw new SQLException("Can't find class for driver: " +
                             driver);
    }
  }

  public synchronized void free(Connection connection) {
    busyConnections.removeElement(connection);
    availableConnections.addElement(connection);
    notifyAll(); 
  }

  public synchronized int totalConnections() {
    return(availableConnections.size() +
           busyConnections.size());
  }
}

包 mil.dlas.database;

public synchronized void getConn()
{
    try
    {
        try
        {
            if(dataSource == null)
            {
                dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/mydb");
            }
            conn = dataSource.getConnection();
            webBasedConnection = true;
        }
        catch (NamingException e){getConnInterfaceBased}
        catch(SQLException e){getConnInterfaceBased();}
    }
    catch(Exception ex){getConnInterfaceBased();}
}    
public synchronized void insertOrUpdatePS(String query, Object[] param)
{
    java.sql.PreparedStatement pStat = null;
    String jobnumber = "";

    try
    {
        getConn();
        if(!webBasedConnection)
            conn = checkOut();

        pStat = conn.prepareStatement(query);

        for(int i=0; i<param.length;i++)
        {
            if (i==0)
                jobnumber = param[i].toString();

            pStat.setObject(i+1,param[i]);
        }

        int insertUpdateReturnCode = pStat.executeUpdate();
        ResultSet rs = pStat.getGeneratedKeys();
        if (rs.next())
        {
            ResultSetMetaData rsmd = rs.getMetaData();
            int colCount = rsmd.getColumnCount();
            String columnOneName = rsmd.getColumnName(1);

            for (int x = 1; x <= colCount; x++)
            {
                String key = rs.getString(x);
                this.autoIncrementedID = key;
            }
        }
        else
        {
            this.autoIncrementedID = "";
        }

    }
    catch(SQLException e){e.printStackTrace();}
    catch(Exception e){e.printStackTrace();}
    finally
    {
        if(pStat!=null)            
           try {pStat.close();}
            catch(SQLException e){}             
        if(this.webBasedConnection)
            returnConn();
        else
            checkIn(conn);
    }
}
package mil.dlas.database;

import java.util.*; 
import java.sql.*; 
public class ConnectionPool implements Runnable 
{      
    private int m_InitialConnectionCount = 3;   
    private Vector m_AvailableConnections = new Vector(); 
    private Vector m_UsedConnections = new Vector(); 
    private String m_URLString = null; 
    private String m_UserName = null;     
    private String m_Password = null;
    private Thread m_CleanupThread = null; 

    protected ConnectionPool(String urlString, String user, String passwd) throws SQLException 
    {  
        m_URLString = urlString; 
        m_UserName = user; 
        m_Password = passwd; 

        for(int cnt=0; cnt<m_InitialConnectionCount; cnt++) 
        { 
            m_AvailableConnections.addElement(getConnection()); 
        }         
        m_CleanupThread = new Thread(this); 
        m_CleanupThread.start(); 
    }     

    private Connection getConnection() throws SQLException
    { 
        return DriverManager.getConnection(m_URLString, m_UserName, m_Password); 
    } 

    public synchronized Connection checkout() throws SQLException 
    { 
        Connection newConnxn = null; 
        if(m_AvailableConnections.size() == 0) 
        { 
             newConnxn = getConnection();  
             m_UsedConnections.addElement(newConnxn); 
        } 
        else 
        {  
            newConnxn = (Connection)m_AvailableConnections.lastElement();
            m_AvailableConnections.removeElement(newConnxn); 
            m_UsedConnections.addElement(newConnxn);  
        }         
        return newConnxn; 
    } 


    public synchronized void checkin(Connection c) 
    { 
        if(c != null) 
        { 
            m_UsedConnections.removeElement(c);
            m_AvailableConnections.addElement(c);         
        } 
    }             

    public int availableCount() 
    { 
        return m_AvailableConnections.size(); 
    } 

    public void run() 
    {
        Connection c = null;
        try { 
            while(true) 
            { 
                synchronized(this) 
                { 
                    while(m_AvailableConnections.size() > m_InitialConnectionCount) 
                    { 
                        c = (Connection)m_AvailableConnections.lastElement();
                        m_AvailableConnections.removeElement(c); 
                    } 
                }                   
                Thread.sleep(60000 * 1);
            }     
        }
        catch(Exception e) { e.printStackTrace(); } 
        finally {
           try{if (c != null) c.close();}
           catch(SQLException sqle) { sqle.printStackTrace(); } 
        }
    }

    public void closeConns() throws SQLException 
    { 
        try {
             for(int cnt=0; cnt<=m_AvailableConnections.size(); cnt++) 
             { 
                 Connection c = (Connection)m_AvailableConnections.lastElement(); 
                 c.close();
                 m_AvailableConnections.removeElement(c); 
             }
        }
         catch(Exception e) { e.printStackTrace(); } 
    } 
} 

在整个代码中,我看到对这两个类的调用:

Database db = new Database();
db.insertOrUpdatePS(qstring.toString(), param);

Database dbAddMember = (Database) ssb.getObject("db");
dbAddMember.insertOrUpdatePS(qstring, param, eb);

可以安全地假设我们与我们正在使用的数据库不一致吗?

由于所有从事此工作的人都已经离开,我如何弄清楚为什么有人会使用其中一个而不是另一个,以及我是否应该考虑删除一个?

我该如何查找这里是否有东西导致泄漏?

关于如何解决这个问题有什么建议吗?

最佳答案

老实说,这段代码实在是太糟糕了。并不是因为您有自定义数据库连接处理,而是因为遗留代码正在同步获取数据库访问的方法,这意味着一次只会执行一个 SQL 语句,这不好。

您不一定要责怪遗留代码尝试连接池的解决方案,但在当今时代,您可以放心地假设有比多年前自定义编写的任何解决方案更好且经过验证的解决方案。

许多用户都会对可用于完成工作的最佳库有自己的看法,但我会说我在使用以下方法的几个项目中取得了非常好的成功:

JTDS 是一个优秀的数据库驱动程序 ( http://jtds.sourceforge.net/ )

Atomikos 用于事务管理 ( http://www.atomikos.com/Documentation/WebHome )

用于连接池的 DBCP ( https://commons.apache.org/proper/commons-dbcp/ )

还有很多很多其他的。 无论如何,从我看来,您肯定会看到在决定用经过验证的真实库替换自定义代码以完成工作时会有所改进。

关于java - 整个代码中未正确使用数据库连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35518292/

相关文章:

events - 剑道 UI 数据源更改事件 : is it working?

java - 为什么 Spring boot 无法识别我的第二个数据源配置?

google-sheets - 应如何将 boolean 值存储在 Google 数据洞察数据源的 Google 表格中?

java - 无法使用 API v2 Foreman 1.7.1 创建主机

mysql - 从另一个ip地址连接到xampp mysql

java - 在开始另一个 Activity 之前使用 Thread.sleep(Milliseconds) 等待一下是一种不好的做法吗?

excel - 使用 VBA 将 MS Access 数据库查询导入 Excel,无需登录提示

mysql - 数据库数据完整性问题

java - 模拟私有(private)包装器/基元/字符串字段

java - 如何自动创建批处理/shell 脚本来运行 Java 控制台应用程序?