Domanda

I am using singleton database connection inside my java application, here is code of my connection manager class:

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);
        }
     }
}

The problem is my code work perfect at the start but when time past it becomes really slow. What caused that problem and how can i fix that? At starting time my application handles around 20 queries per second, after 1 hour of running it reaches to 10 queries per second and after 3 days of running it reaches to 1 query per 10 seconds!! P.S: My application is a single user application that makes many queries through database. P.S: Here is my JVM parameters in eclipse.ini:

--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

Unfortunately database is remote and I have not any monitoring access to it for finding out what is going on there.

Here is the example of my usage:

String count="select count(*) as counter from TSN";
ResultSet rscount=DatabaseManager.executeQuery(count, "SNfinal");
if(rscount.next()) {
    numberofNodes=rscount.getInt("counter");
}
È stato utile?

Soluzione 2

You should consider using a disconnected resultset like a CachedRowSet http://docs.oracle.com/javase/1.5.0/docs/api/javax/sql/rowset/CachedRowSet.html

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 implements ResultSet so it should behave like a ResultSet.

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

In addition to these changes, I would recommend you use a pooled datasource to get connections and close them instead of holding on to one open connection.

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

Or if you arent java7, bonecp or c3po.

EDIT:

To answer your question, this solves your problem because CachedRowSetImpl doesnt stay connected to the database while in use. This allows you to close your Resultset and Statement after you've populated the CachedRowSetImpl.

Hope that answers your question.

Altri suggerimenti

What caused that problem and how can i fix that?

The main problem that you have here is in the executeQuery() method. You are not closing the Statement, I suppose that you have commented the line st.close() because you need the ResultSet open for further processing. I can see that your idea is to avoid see duplicate JDBC code in your application, but this is not the right approach.

The rule is: close the ResultSet and after that, close the Statement, otherwise you are not releasing resources correctly and you expose to the kind of problem that you are describing.

Here you can find a good explanation about how to close resources correctly (take in mind that in your case you don´t need to close the connection)

Edit: An example could be

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();
}
  1. Although Connection Manager would close Statement and Resultset automatically, but it would be better if you close them immediately.

  2. There's nothing else in your code will effect your single thread task, so I bet there must be something wrong in your database. Try to find out if there's any database locking or wrong column index. And also have a look at database query status, find out where's the bottleneck.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top