簡體   English   中英

如何正確關閉數據源連接?

[英]How to properly close datasource connection?

我有這個課程,但我不確定如何正確關閉連接,因為即使我只有 3 個用戶登錄但有多個 sql 查詢,我仍然有這個錯誤。

 > com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: > Data source rejected establishment of connection, message from > server: "Too many connections"
import java.io.File;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.sql.DataSource;

public class UserDaoImpl implements UserDao
{

    DataSource dataSource;

    public DataSource getDataSource()
    {
            return this.dataSource;
    }

    public void setDataSource(DataSource dataSource)
    {
            this.dataSource = dataSource;
    }


    public boolean isValidUser(String username, String password) throws SQLException
    {       
        PreparedStatement pstmt = null;
        ResultSet resultSet = null;
        boolean rt = false;
        try{
            PasswordEncryptor pws = new PasswordEncryptor();
            String encryptedPass = pws.encrypt(password);

            String query = "Select count(1) from userdetails where username = ? and password = ?";
            pstmt = dataSource.getConnection().prepareStatement(query);
            pstmt.setString(1, username);
            pstmt.setString(2, encryptedPass);
            resultSet = pstmt.executeQuery();
            if (resultSet.next()){
                    rt =  (resultSet.getInt(1) > 0);
            }
            else{
                rt = false;
            }
    }
    catch(Exception e){
        e.printStackTrace();

    }
    finally{
        resultSet.close();
        pstmt.close();
        dataSource.getConnection().close();
    }

        return rt;  
    }
}

配置文件

    <bean name="userDao" class="com.spring.acadconnect.services.UserDaoImpl">
   <property name="dataSource" ref="dataSource"></property>
   </bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver" />

    <property name="url" value="jdbc:mysql://localhost:3306/acadconnect" />

    <property name="username" value="root" />

    <property name="password" value="" />

</bean>

請注意,您多次調用.getConnection() 盡管文檔在這方面可能更清楚,但DataSource.getConnection()實際上打開了一個新連接(而不是返回現有連接),因此您需要關閉從該方法返回的每個實例。

由於.getConnection()每次被調用時都會創建一個新實例,此行是連接泄漏,因為它沒有關閉返回的連接:

pstmt = dataSource.getConnection().prepareStatement(query);

這條線浪費地打開一個新連接,只是為了立即關閉它:

dataSource.getConnection().close();

看起來您正在嘗試為isValidUser()每次調用打開和關閉單獨的連接(因為您在該方法調用結束時關閉連接)。 即使您修復了上述泄漏,也不是打算使用連接的方式。 相反,您應該在您的應用程序中共享一個連接(或少數連接)。 因此,當您的程序啟動時,您打開這樣一個連接,一旦整個程序不再需要該連接(通常在終止前不久),您就關閉它。

這種行為通常通過依賴注入來實現,您可以在其中構建連接和其他資源,然后將它們傳遞給需要它們的任何對象 - 這將資源管理與使用這些資源的代碼分離。 作為一個簡單的例子:

public static void main(String[] args) {
  DataSource dataSource = createDataSource();
  try (Connection connection = dataSource.getConnection()) {
    runProgram(connection);
  }
}


/**
 * this method doesn't need to worry about closing the Connection,
 * it trusts that its caller will be responsible for that.
 */
private static void runProgram(Connection connection) {
  // ...
}

根據經驗,對象應該只負責關閉它們構造的對象,並且應該避免關閉傳遞給它們的對象。 在您當前的代碼中UserDaoImpl正在打開連接,因此它應該負責關閉它,但我建議改為傳入Connection

dataSource.getConnection()將始終為您返回一個新連接,因此您不會關閉您認為的連接。 您必須使用DataSourceUtils.getConnection()來獲取當前線程的活動連接,否則存儲返回的引用,如 conn = dataSource.getConnection() 和調用conn.close()

試試這個。

conn = dataSource.getConnection();
pstmt = conn.prepareStatement(query);

稍后當您不再需要連接到數據庫時,只需關閉使用

conn.close();

更新:

Connection conn = dataSource.getConnection();
PreparedStatement ps = pstmt = conn.prepareStatement(query);

try {
    // ur code
}
catch (SQLException ex) 
{
    // Exception handling
} 
finally 
{
    if (rs != null) 
{
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) { out.print(e)} // This will print exception to help better
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { out.print(e)}
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM