3

In C# I am able to create a class like this:

static class clsDBUtils
{
        public static SQLiteCommand cmd;
        public static SQLiteConnection conn;
        public static String databaseFilePath;

        public static bool getConnection()
        {
        }
}

Then anywhere in my namespace can use without initialization this way:

clsDBUtils.getConnection();

How can this be rewritten for Java?

I don't want to use:

clsDBUtils sqlutil= new clsDBUtils();
Pentium10
  • 204,586
  • 122
  • 423
  • 502

5 Answers5

9

Basically the same way, just make a (normal) final class with a private contructor (prevents being able to do new) and add static members only.

public final class clsDBUtils {
    public static SQLiteCommand cmd;
    public static SQLiteConnection conn;
    public static String databaseFilePath;

    public static bool getConnection() {
    }

    private clsDBUtils() {}
}
Lucero
  • 59,176
  • 9
  • 122
  • 152
5

Apart from the particular question/problem, it is bad practice to declare expensive and external resources like Connection, Statement and ResultSet as an instance variable, let alone as a static variable. Those resources doesn't have an endless lifetime and your application may break when the DB decides to timeout the connection because it hasn't been released back to the DB after use.

I can't imagine that it's done differently in C# (it would have been a bug in the application as well), but the normal JDBC idiom is that you acquire and close it in the shortest possible scope, thus already inside the very same method block. E.g.

public Entity find(Long id) throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    Entity entity = null;

    try {
        connection = database.getConnection();
        statement = connection.prepareStatement(SQL_FIND);
        statement.setLong(1, id);
        resultSet = statement.executeQuery();

        if (resultSet.next()) {
            entity = new Entity();
            entity.setProperty(resultSet.getObject("columnname"));
            // etc..
        }
    } finally {
        // Always free resources in reversed order.
        if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
        if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
        if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
    }

    return entity;
}

The database.getConnection() can however technically perfectly be made static like this:

public final class Database {
    static {
        try {
            Class.forName("com.example.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private Database() {
        // No need to instantiate this class.
    }

    public static Connection getConnection() {
        DriverManager.getConnection("jdbc:example://localhost/dbname", "user", "pass");
    }
}

so that you can use it as

connection = Database.getConnection();

(which you still really need to close in the finally block after use!)

However, this makes the connection source also really static. You cannot take benefit of polymorphism and/or inheritance anymore to switch between connection sources, such as a connection pool (to get better performance). To get more ideas/insights you may find this article useful

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • by connecting and disconnecting each time, will the app be slower? – Pentium10 Feb 10 '10 at 14:25
  • That's what the connection pool is for and that's also why I hinted about it in my answer. I can recommend to grab c3p0 for that: http://sourceforge.net/projects/c3p0/ – BalusC Feb 10 '10 at 14:26
  • I will use on Android. I was told that on mobile is better to open a connection at startup and close when the app exists, while on desktop apps is advised to open and close connection after you are done within that window. On mobile the open process can take lot of resources, and it can be painful to do that many times. I understand that before executing a query we has to assure there is an active connection (OS can close it) – Pentium10 Feb 10 '10 at 14:35
  • so what do you think, on mobile is better to open only once the connection for a while? – Pentium10 Feb 10 '10 at 14:37
  • 1
    The app may live longer than a connection is allowed to be opened. So, no, I wouldn't open it that long time. Use a connection pool or just reopen on every query. I assume that it's just a local/embedded database, so connecting shouldn't be that expensive then. – BalusC Feb 10 '10 at 15:09
  • It will be a one-user-client connection. Does it worth having a Connection Pool? – Pentium10 Feb 10 '10 at 15:16
  • If local/embedded database, then connecting shouldn't be expensive, then it is less worth having a connection pool. Profiling/benchmarking should however give the best answer on your particular situation. – BalusC Feb 10 '10 at 16:22
1

The code for it is almost exactly the same (same concept, slightly different syntax)

public class ClsDBUtils
{
    public static SQLiteCommand cmd;
    public static SQLiteConnection conn;
    public static String databaseFilePath;

    public static boolean getConnection()
    {
    }
}

// somewhere else
ClsDBUtils.getConnection();
RHSeeger
  • 16,034
  • 7
  • 51
  • 41
0

Just declare a public class and use the 'static' modifier on your methods and fields. If you do not want it to be instantiated, use 'public final class '. Alternatively, you can use a singleton class.

Marcel Gheorghita
  • 1,853
  • 13
  • 19
0

You want to implement the Singleton pattern: http://en.wikipedia.org/wiki/Singleton_pattern

public class clsDBUtils {
   private static final clsDBUtils INSTANCE = new clsDBUtils();

   // Private constructor prevents instantiation from other classes
   private clsDBUtils() {}

   public static clsDBUtils getInstance() {
      return INSTANCE;
   }

   public SQLiteCommand cmd;
   public SQLiteConnection conn;
   public String databaseFilePath;

   public bool getConnection()
   {
   }
 }

You can then use the following syntax on your class:

clsDBUtils.getInstance().getConnection();
seanhodges
  • 17,426
  • 15
  • 71
  • 93
  • NO NO NO. You've done it wrong. Use enum instead of class or remember to override readResolve. See Item 77 of _Effective Java_. – KitsuneYMG Feb 10 '10 at 14:12
  • I don't follow. The poster has not asked for the class to be serialisable, so it has no need for readResolve(). The above pattern is a simple Singleton implementation - see page 127 of Design Patterns: Elements of Reusable Object-Oriented Software – seanhodges Feb 10 '10 at 15:57