gpt4 book ai didi

java - 数据库连接在两个应用程序之间共享的对象的整个生命周期内打开

转载 作者:行者123 更新时间:2023-11-29 20:55:06 25 4
gpt4 key购买 nike

应用:

  1. Web 应用程序,它将充当独立应用程序。[Servlet3.0技术]
  2. Windows 应用程序,将以 jar 文件形式提供。

数据库:

  1. MySQL

数据库助手类

我们有在上述两个应用程序之间共享的数据库帮助程序类。

数据库助手类具有所有静态方法,例如下面是用户验证方法。

    public static boolean validate(String name, String pass) {
Connection dbConnection = null;
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
//checkDbConnection();

try {
dbConnection = getDBConnection();

String query = "SELECT * FROM " + TABLE_USERS + " WHERE " + USERS_USERNAME + " = ? AND " + USERS_PASSWORD
+ " = ?";
preparedStatement = ZMCdbConnection.prepareStatement(query);
preparedStatement.setString(1, name);
preparedStatement.setString(2, pass);
resultSet = preparedStatement.executeQuery();
return resultSet.next();

} catch (Exception e) {
System.out.println(e);
return false;
} finally {
closeResources(dbConnection, preparedStatement, resultSet);
}
}

查询

对于每个方法,最后我们将关闭所有数据库资源,例如PreparedStatement、ResultSet、dbConnection。

然后我们收到了来自高级代码审查员的以下评论,

哇,每次查询后都关闭数据库连接?这是非常低效的。最好在该对象的生命周期内保持其打开状态。 (请注意,这可能意味着查询需要能够适应偶尔的断开连接,即在出错时尝试一个简单的查询(如“select 1”),如果失败,则重新建立连接并重新尝试原始查询。

根据我们的理解,一旦 Activity 完成,数据库连接就应该始终关闭。然而,为了支持审稿人的评论,我们想到了 2 个解决方案,我们觉得这两个解决方案的说服力稍差。

解决方案1

现在,为了更改数据库连接在对象的整个生命周期中保持打开状态的逻辑,我们开发了以下方法,该方法将在上述方法的顶部调用。

    private static void checkDbConnection() {
if (ZMCdbConnection == null) {
ZMCdbConnection = getDBConnection();
}

boolean querySuccess = false;
try {
String query = "select 1";
PreparedStatement ps = ZMCdbConnection.prepareStatement(query);
querySuccess = ps.execute();
} catch (Exception e) {
}
if (!querySuccess) {
ZMCdbConnection = getDBConnection();
}
}

优点:

我们确保我们始终获得打开的 dbconnection 对象。

缺点:

每个方法都进行不必要的额外调用。

解决方案2

  1. 第一次在静态 block 的数据库帮助器类中打开一次 dbconnection。
  2. 从 Servlet 调用数据库帮助器方法并执行查询。
  3. 如果查询失败,请尝试“select 1”查询以确保 dbconnection 已关闭。
  4. 如果失败,则向调用数据库帮助器方法的 Servlet 发送“dbconnection close”异常。
  5. 再次调用该方法,数据库连接将在第 1 步打开。

有人可以建议其他解决方案吗?

最佳答案

让我回答我自己的问题。

我知道过去已经回答了类似的问题,但仍然让我尝试一下我的案例,以防有人需要。

实现:连接池机制

使用的库: Commons DBCP2

实现:

public class DatabaseHelper {
public static final BasicDataSource dataSource = new BasicDataSource();

static {
setDataSourceParameter();
}

public static void setDataSourceParameter() {
try {
dataSource.setDriverClassName(H2_DB_DRIVER);
dataSource.setUrl(H2_DB_CONNECTION);
dataSource.setUsername(H2_DB_USER);
dataSource.setPassword(H2_DB_PASSWORD);
dataSource.setValidationQuery("SELECT 1");
LOGGER.log(Level.DEBUG, "setDataSourceParameter()");
} catch (Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e.fillInStackTrace());
}
}

/**
* This method returns a database connection used for database query
*
* @return Connection
*/
public static Connection getDBConnection() throws SQLException {
LOGGER.log(Level.DEBUG, "getDBConnection() : getNumActive : " + dataSource.getNumActive());
LOGGER.log(Level.DEBUG, "getDBConnection() : getNumIdle : " + dataSource.getNumIdle());
return dataSource.getConnection();
}

/**
* This method closes database related resources
*
* @param connection
* @param statement
* @param resultSet
*/
public static void closeResources(Connection connection, PreparedStatement statement, ResultSet resultSet) {
try {
if (statement != null) {
statement.close();
}
if (resultSet != null) {
resultSet.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
LOGGER.log(Level.ERROR, e.getMessage(), e.fillInStackTrace());
}
}
}

public static boolean validate(String username, String password) {
Connection dbConnection = null;
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;

try {
dbConnection = getDBConnection();
if (dbConnection == null) {
return false;
}

String query = "SELECT * FROM " + TABLE_USERS + " WHERE " + USERS_USERNAME + " = ? AND " + USERS_PASSWORD
+ " = ?";
LOGGER.log(Level.TRACE, "validate() : query " + query);
preparedStatement = dbConnection.prepareStatement(query);
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
resultSet = preparedStatement.executeQuery();

return resultSet.next();
} catch (Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e.fillInStackTrace());
return false;
} finally {
closeResources(dbConnection, preparedStatement, resultSet);
}
}

创建数据库连接池

在应用程序启动时调用setDataSourceParameter()方法。

使用连接

从将运行 SQL 查询的方法中调用 getDBConnection() 方法[引用 validate() 方法]。

将连接返回到池

查询执行完成后调用closeResources()方法[引用validate()方法]。

关于java - 数据库连接在两个应用程序之间共享的对象的整个生命周期内打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37705344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com