我还在处理提到here的同一问题。它似乎工作正常,特别是在创建如下所示的AbstractModel类之后:
public abstract class AbstractModel {
protected static Connection myConnection = SingletonConnection.instance().establishConnection();
protected static Statement stmt;
protected static ResultSet rs;
protected boolean loginCheck; // if userId and userLoginHistoryId are valid - true, else false
protected boolean userLoggedIn; // if user is already logged in - true, else false
public AbstractModel (int userId, Long userLoginHistoryId){
createConnection(); // establish connection
loginCheck = false;
userLoggedIn = false;
if (userId == 0 && userLoginHistoryId == 0){ // special case for login
loginCheck = true; // 0, 0, false, false
userLoggedIn = false; // set loginCheck to true, userLogged in to false
} else {
userLoggedIn = true;
try{
String query = "select \"user_login_session_check\"(" + userId + ", " + userLoginHistoryId + ");";
System.out.println("query: " + query);
stmt = myConnection.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()){
loginCheck = rs.getBoolean(1);
}
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
}
}
// close connection
public void closeConnection(){
try{
myConnection.close();
} catch (SQLException e){
System.out.println("SQL Exception: ");
e.printStackTrace();
}
}
// establish connection
public void createConnection(){
myConnection = SingletonConnection.instance().establishConnection();
}
// login session check
public boolean expiredLoginCheck (){
if (loginCheck == false && userLoggedIn == true){
closeConnection();
return false;
} else {
return true;
}
}
}
我已经在上面上一个问题的链接中发布了存储过程和Singleton Pattern实现。
我的印象是,在每次单个数据事务之后,我不需要关闭与数据库的连接,因为它只会减慢应用程序的速度。我正在为我正在构建的这个系统寻找大约30个用户,因此性能和可用性非常重要。
延长至少3-4次数据交易的连接是否正确?例如。验证检查某些表单的用户输入,或类似于谷歌的自动建议...这些都是基于用户输入的单独存储的函数调用。我可以使用一个连接实例,而不是在每次数据事务后连接和断开连接吗?哪个更有效率?
如果我的假设是正确的(使用一个连接实例更有效),那么应该在控制器中处理连接的打开和关闭,这就是我创建createConnection()和closeConnection()方法的原因。
感谢。
答案 0 :(得分:4)
您的代码永远不应该依赖于以下事实:您的应用程序当前是数据库的唯一客户端,或者您只有30个用户。因此,您应该处理数据库连接,例如文件,套接字以及您可能运行的所有其他稀缺资源。
因此,您应该始终清理自己。无论你做什么。打开连接,做你的东西(一个或SQL语句)和关闭连接。 始终!强>
在您的代码中,您创建连接并将其保存到静态变量中 - 只要您的AbstractModel类存在,此连接将持续,可能永远 - 这很糟糕。与所有类似的情况一样,将代码放在try / finally中以确保连接始终关闭。
由于Web应用程序未关闭连接,我看到应用程序服务器正在运行连接。或者因为他们在退出时关闭,有人说“我们将永远不会有那么多用户同时”,但它只是缩小了一点点。
现在,当您运行代码并正确关闭连接时,添加连接池,就像zaske所说。这将解决打开/关闭数据库连接的性能问题,这实际上是昂贵的。在逻辑层(您的应用程序)上,您不想知道何时打开/关闭物理连接,db层(db pool)将为您处理它。
然后你甚至可以为你的整个会话模型设置一个连接,这也是DBCP支持的 - 这没有危险,因为如果你需要,你可以在不需要触及客户端代码的情况下重新配置池。
答案 1 :(得分:4)
像Tomasz所说,你应该从不 永远 取决于您的应用程序将被少数客户使用的事实。在一定时间后,驱动程序 将 超时的事实并不能保证您将拥有足够的可用连接。想象一下:很多数据库预先配置了最大连接数设置为(比如说)15和超时(比方说)10-15分钟。如果你有30个客户端并且每个客户端都进行了一次操作,那么在中途的某个地方,你将无法完成连接。
您应该通过以下方式处理连接,文件,流和其他资源:
public void doSomething()
{
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
final String sql = "SELECT ....");
try
{
connection = getConnection();
stmt = connection.createStatement();
rs = stmt.executeQuery(sql);
if (rs.next())
{
// Do something here...
}
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
closeResultSet(rs);
closeStatement(stmt);
closeConnection(connection);
}
}
try / catch / finally保证无论结果如何,连接都将被关闭。如果出现某种故障,finally块仍将关闭连接,就像它可以做的那样,如果一切正常的话。
同样,对于文件和流,您需要做同样的事情。在try / catch / finally之外将相应对象初始化为null
,然后按照上面的方法。
这种误解使得许多Java应用程序在Windows下行为不端,人们不会关闭文件(流到文件等)并且这些文件被锁定,迫使你要么杀掉JVM,要么重启你的机器。 / p>
您也可以使用连接池,例如Apache的DBCP,但即使这样,您也应该关闭资源,尽管在内部,不同的连接池实现不一定会关闭连接。
答案 2 :(得分:0)
你是对的,你不需要在每次通话后关闭连接。
请记住,现代数据库实现内部连接池,但您的应用程序仍然需要连接和检索连接对象,这就是它现在所做的。
您应该考虑使用数据库连接池 - 有各种Java框架为您提供这样的解决方案,并且它们将在关闭数据库连接池时定义(当然您将能够配置)。
一般情况下 - 您应该问自己,您的数据库是仅为您的应用程序提供服务,还是为其他应用程序提供服务 - 如果它不能为其他应用程序提供服务,您可能会更“贪婪”并保持连接打开更长的时间。
我还建议您的应用程序在启动时创建固定数量的连接(在您的配置中使用“最小连接数”值定义),如果需要最大连接数,您将使其增长。
正如我之前提到的 - 建议的想法已经由各种框架实现,例如Apache的DBCP项目。
答案 3 :(得分:0)
这是Singleton模式,我将所有模型中的myConenction字段初始化为:
public class DatabaseConnection {
private static final String uname = "*******";
private static final String pword = "*******";
private static final String url = "*******************************";
Connection connection;
// load jdbc driver
public DatabaseConnection(){
try{
Class.forName("org.postgresql.Driver");
establishConnection();
} catch (ClassNotFoundException ce) {
System.out.println("Could not load jdbc Driver: ");
ce.printStackTrace();
}
}
public Connection establishConnection() {
// TODO Auto-generated method stub
try{
connection = DriverManager.getConnection(url, uname, pword);
} catch (SQLException e){
System.out.println("Could not connect to database: ");
e.printStackTrace();
}
return connection;
}
}
public class SingletonConnection {
private static DatabaseConnection con;
public SingletonConnection(){}
public static DatabaseConnection instance(){
assert con == null;
con = new DatabaseConnection();
return con;
}
}
当然,从应用程序到数据库的每个连接都通过模型。