首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >传统的DB单例连接工作效率很低。

传统的DB单例连接工作效率很低。
EN

Stack Overflow用户
提问于 2013-12-21 06:21:33
回答 3查看 945关注 0票数 6

我在我的java应用程序中使用单例数据库连接,下面是我的连接管理器类的代码:

代码语言:javascript
复制
public abstract class DatabaseManager {
    //Static instance of connection, only one will ever exist
        private static Connection connection = null;    
        private static String dbName="SNfinal";
        //Returns single instance of connection
        public static Connection getConnection(){       
            //If instance has not been created yet, create it
            if(DatabaseManager.connection == null){
                initConnection();
            }
            return DatabaseManager.connection;
        }   
        //Gets JDBC connection instance
        private static void initConnection(){           
            try{        
                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
                   String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
                      "databaseName="+dbName+";integratedSecurity=true";

                DatabaseManager.connection =
                             DriverManager.getConnection(connectionUrl);        
            }
            catch (ClassNotFoundException e){       
                System.out.println(e.getMessage());
                System.exit(0);
            }
            catch (SQLException e){         
                System.out.println(e.getMessage());
                System.exit(0);
            }
            catch (Exception e){        
            }       
        }
    public static ResultSet executeQuery(String SQL, String dbName)
    {
        ResultSet rset = null ;
        try {
               Statement st = DatabaseManager.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
               rset = st.executeQuery(SQL);
               //st.close();
        }
        catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
        return rset;
     }

    public static void executeUpdate(String SQL, String dbName)
    {
        try {
               Statement st = DatabaseManager.getConnection().createStatement();
               st.executeUpdate(SQL);
               st.close();
        }

        catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
     }
}

问题是,我的代码在一开始就工作得很完美,但当时间流逝时,它变得非常缓慢。是什么引起了这个问题,我该怎么解决呢?在启动时,我的应用程序每秒处理大约20个查询,运行1小时后达到每秒10个查询,运行3天后达到每10秒1个查询!!P.S:我的应用程序是一个单用户应用程序,它通过数据库进行许多查询。P.S:以下是eclipse.ini中的JVM参数:

代码语言:javascript
复制
--launcher.XXMaxPermSize
512M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-Xms500m
-Xmx4G
-XX:MaxHeapSize=4500m

不幸的是,数据库是远程的,我没有任何监视访问权限来了解那里发生了什么。

下面是我的用法示例:

代码语言:javascript
复制
String count="select count(*) as counter from TSN";
ResultSet rscount=DatabaseManager.executeQuery(count, "SNfinal");
if(rscount.next()) {
    numberofNodes=rscount.getInt("counter");
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-28 15:32:28

应该考虑使用像CachedRowSet http://docs.oracle.com/javase/1.5.0/docs/api/javax/sql/rowset/CachedRowSet.html那样的断开连接的结果集。

代码语言:javascript
复制
public static ResultSet executeQuery(String SQL, String dbName)
{
    CachedRowSetImpl crs = new CachedRowSetImpl();
    ResultSet rset = null ;
    Statement st = null;
    try {
           st = DatabaseManager.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
           rset = st.executeQuery(SQL);
           crs.populate(rset);
    }
    catch (SQLException e) {
        System.out.println(e.getMessage());
        System.exit(0);
    }finally{
        rset.close();
        st.close();
    }
    return crs;
 }

CachedRowSet实现了ResultSet,因此它的行为应该像ResultSet。

http://www.onjava.com/pub/a/onjava/2004/06/23/cachedrowset.html

除了这些更改之外,我建议您使用池数据源获取连接并关闭它们,而不是保留一个打开的连接。

http://brettwooldridge.github.io/HikariCP/

或者如果你没有java7,bonecp或c3po。

编辑:

为了回答您的问题,这解决了您的问题,因为CachedRowSetImpl在使用时不与数据库保持连接。这允许您在填充ResultsetStatement之后关闭CachedRowSetImpl

希望这能回答你的问题。

票数 1
EN

Stack Overflow用户

发布于 2013-12-22 02:47:37

是什么引起了这个问题,我该怎么解决呢?

这里的主要问题是executeQuery()方法。您没有关闭Statement,我想您已经注释了行st.close(),因为您需要打开ResultSet以便进一步处理。我可以看到,您的想法是避免在应用程序中看到重复的JDBC代码,但这不是正确的方法。

规则是:关闭ResultSet,然后关闭Statement,否则就不能正确释放资源,并且暴露在所描述的问题中。

这里您可以找到一个很好的解释,说明如何正确关闭资源(请记住,在您的情况下,不需要关闭连接)

编辑:可以是一个例子

代码语言:javascript
复制
try{
Statement st = DatabaseManager.getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rsCount = st.executeQuery(count);         //count="select count(*) as counter from TSN";
if(rsCount.next()) {
    numberofNodes=rscount.getInt("counter");
}
} catch (SQLException e) {
    //log exception
} finally {
    rsCount.close();
    st.close();
}
票数 3
EN

Stack Overflow用户

发布于 2013-12-22 02:19:52

  1. 虽然连接管理器会自动关闭StatementResultset,但最好立即关闭它们。
  2. 您的代码中没有任何其他内容会影响您的单线程任务,所以我打赌您的数据库中肯定有错误。尝试找出是否存在任何数据库锁定或列索引错误。并查看数据库查询状态,找出瓶颈在哪里。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20716169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档