簡體   English   中英

JDBC連接過多

[英]JDBC too many connections

以下是連接方法:

private static Connection connection = null;

/**
 * Gets the database connection.
 */
public static Connection getConnection() {
    return Storage.connection;
}

/**
 * Connects to the database.
 */
public static void connectToDatabase() {
    try {
        String userName = "root";
        String password = "mysql";
        String url = "jdbc:mysql://localhost/secondsemesterprojectdanishcrowncaos";
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        Storage.connection = DriverManager.getConnection(url, userName,
                password);
        Storage.connection
                .setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
        Storage.connection.setAutoCommit(false);
    } catch (Exception e) {
        System.err.println("Cannot connect to database server." + e);
    }
}

/**
 * Terminates the database connection.
 */
public static void disconnectDatabase() {
    if (Storage.connection != null) {
        try {
            Storage.connection.close();
        } catch (Exception e) {
        }
    }
}

這是我的連接和查詢:我所有的數據庫連接都與此連接幾乎相同:

public void addLoadingDock(LoadingDock loadingDock) {
    loadingDocks.add(loadingDock);

    Storage.connectToDatabase();

    PreparedStatement s;
    try {
        String query = "INSERT INTO LoadingDocks(dock_no, active, product_type_id) VALUES (?, ?, ?);";
        s = Storage.connection.prepareStatement(query,
                Statement.RETURN_GENERATED_KEYS);
        s.setInt(1, loadingDock.getDockNo());
        s.setBoolean(2, loadingDock.getActive());
        s.setInt(3, loadingDock.getProductType().getId());
        int rows = s.executeUpdate();
        Storage.connection.commit();
        System.out.println(rows + " row(s) created in database");
        ResultSet generatedKeys;
        generatedKeys = s.getGeneratedKeys();
        if (generatedKeys.next()) {
            loadingDock.setId(generatedKeys.getInt(1));
        } else {
            throw new SQLException(
                    "Creating LoadingDock failed, no generated key obtained.");
        }
        generatedKeys.close();
        s.close();
    } catch (Exception e) {
        System.err.println("Error adding LoadingDock. Details: " + e);
        try {
            Storage.connection.rollback();
        } catch (SQLException e1) {
            System.err.println("Error on rollback. Details: " + e1);
        }
    } finally {
        Storage.disconnectDatabase();
    }
}

一時程序遇到太多的連接問題。

請告訴我,連接出了什么問題。 我沒有正確關閉它們的地方? 或其他任何問題。

兩件事讓我驚訝...

  1. 您應該避免以這種方式使用static ...
  2. 在創建Connection之前,您從不檢查Connection是否為null ,因此流氓連接可能仍在運行,例如...

如果您有兩段代碼來創建連接的實例,而第二段代碼是在關閉第一個實例之前創建的,則僅處置Connection的第二個實例

Storage.connectToDatabase();
//...
Storage.connectToDatabase();
//...
Storage.disconnectDatabase();

您可以首先在connectToDatabase檢查null ,例如

public static void connectToDatabase() {
    if (Storage.connection == null) {
        try {
            String userName = "root";
            String password = "mysql";
            String url = "jdbc:mysql://localhost/secondsemesterprojectdanishcrowncaos";
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Storage.connection = DriverManager.getConnection(url, userName,
                    password);
            Storage.connection
                    .setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
            Storage.connection.setAutoCommit(false);
        } catch (Exception e) {
            System.err.println("Cannot connect to database server." + e);
        }
    }
}

為了克服對static的使用,您可以使用singlton模式,例如...

public enum Storage {

    INSTANCE;

    private static Connection connection = null;

    /**
     * Gets the database connection.
     */
    public Connection getConnection() {
        return connection;
    }

    /**
     * Connects to the database.
     */
    public void connectToDatabase() {
        if (connection == null) {
            try {
                String userName = "root";
                String password = "mysql";
                String url = "jdbc:mysql://localhost/secondsemesterprojectdanishcrowncaos";
                Class.forName("com.mysql.jdbc.Driver").newInstance();
                connection = DriverManager.getConnection(url, userName,
                        password);
                connection
                        .setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
                connection.setAutoCommit(false);
            } catch (Exception e) {
                System.err.println("Cannot connect to database server." + e);
            }
        }
    }

    /**
     * Terminates the database connection.
     */
    public void disconnectDatabase() {
        if (connection != null) {
            try {
                connection.close();
            } catch (Exception e) {
            }
        }
    }
}

這樣可以保證Storage的單個實例,並且可以確保對Connection更好的管理(如果仔細完成的話)。

另一種選擇是使用某種類型的連接池,這將允許它為您管理連接。

使用連接池。 有很多可用的,但是c3p0bonecp很流行。 連接池將使您可以更輕松地重用數據庫連接,從而不會耗盡最大數量的“開放”資源。

暫無
暫無

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

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