gpt4 book ai didi

java - 如何正确关闭数据源连接?

转载 作者:可可西里 更新时间:2023-11-01 07:36:30 24 4
gpt4 key购买 nike

我有这个类(class),但我不确定如何正确关闭连接,因为即使我只有 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;
}
}

SpringConfiguration.xml

    <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() 打开和关闭一个单独的连接(因为您是在该方法调用结束时关闭连接)。即使您修复了上述泄漏,这也不是连接的预期使用方式。相反,您应该在您的应用程序中共享一个连接(或其中的一小部分)。因此,当您的程序启动时,您打开这样一个连接,一旦整个程序不再需要该连接(通常在终止前不久),您就关闭它。

这种行为通常由 dependency injection 实现,您可以在其中构建连接和其他资源,然后将它们传递给任何需要它们的对象——这将资源管理与使用这些资源的代码分离。举个简单的例子:

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

关于java - 如何正确关闭数据源连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42398715/

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