23

I wrote a singleton class for obtaining a database connection.

Now my question is this: assume that there are 100 users accessing the application. If one user closes the connection, for the other 99 users will the connection be closed or not?

This is my sample program which uses a singleton class for getting a database connection:

public class GetConnection {

    private GetConnection() { }

    public Connection getConnection() {
        Context ctx = new InitialContext();
        DataSource ds = ctx.lookup("jndifordbconc");
        Connection con = ds.getConnection();
        return con;
    }

    public static  GetConnection   getInstancetoGetConnection () {
        // which gives GetConnection class instance to call getConnection() on this .
    }
}

Please guide me.

deHaar
  • 17,687
  • 10
  • 38
  • 51
hanhu
  • 255
  • 1
  • 3
  • 7
  • 1
    Consider to use use Connection Pool (http://en.wikipedia.org/wiki/Connection_pool). For example, DBCP (http://commons.apache.org/dbcp/). – Slava Semushin Jul 04 '11 at 06:30
  • 1
    @php more than often a JNDI datasource is by default a connection pool already. – BalusC Jul 04 '11 at 07:18
  • 1
    implemented like that it's not a singleton. It's roughly a factory method. What are you trying to achieve? – SRKX Jul 04 '11 at 07:29
  • I honestly thought this question was a duplicate of [this one](http://stackoverflow.com/q/6507687/3775798) until I read it a bit more closely. Suggested a title edit to better reflect this. – Knowledge Cube May 10 '17 at 13:20

5 Answers5

27

As long as you don't return the same Connection instance on getConnection() call, then there's nothing to worry about. Every caller will then get its own instance. As far now you're creating a brand new connection on every getConnection() call and thus not returning some static or instance variable. So it's safe.

However, this approach is clumsy. It doesn't need to be a singleton. A helper/utility class is also perfectly fine. Or if you want a bit more abstraction, a connection manager returned by an abstract factory. I'd only change it to obtain the datasource just once during class initialization instead of everytime in getConnection(). It's the same instance everytime anyway. Keep it cheap. Here's a basic kickoff example:

public class Database {

    private static DataSource dataSource;

    static {
        try {
            dataSource = new InitialContext().lookup("jndifordbconc");
        }
        catch (NamingException e) { 
            throw new ExceptionInInitializerError("'jndifordbconc' not found in JNDI", e);
        }
    }

    public static Connection getConnection() {
        return dataSource.getConnection();
    }

}

which is to be used as follows according the normal JDBC idiom.

public List<Entity> list() throws SQLException {
    List<Entity> entities = new ArrayList<Entity>();

    try (
        Connection connection = Database.getConnection();
        PreparedStatement statement = connection.prepareStatement("SELECT id, foo, bar FROM entity");
        ResultSet resultSet = statement.executeQuery();
    ) {
        while (resultSet.next()) {
            Entity entity = new Entity();
            entity.setId(resultSet.getLong("id"));
            entity.setFoo(resultSet.getString("foo"));
            entity.setBar(resultSet.getString("bar"));
            entities.add(entity);
        }
    }

    return entities;
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Thanks Balusc , i am having one more question , as you are using static method for returning Database connection , if one user closes , than all the connections would be also closed know as static os one per entire Class . please correct me . – hanhu Jul 04 '11 at 08:52
  • 2
    I believe you're confusing static methods with static fields. As long as you don't assign the connection as a static field of the class, there's no problem. – BalusC Jul 04 '11 at 18:23
  • I think what he means if a bunch of classes all call `Database.getConnection()` and after a while one class calls `connection.close()` on the return value of the previous call, doesn't it close the connection for everyone? – Christophe De Troyer Aug 18 '15 at 07:03
  • @ChristopheDeTroyer: I believe you're confusing static methods with static fields. As long as you don't assign the connection as a static field of the class, there's no problem. – BalusC Aug 18 '15 at 07:22
  • Well, I think you don't understand my question. I have two classes `Foo` and `Bar` which each use the `Database` class. They call `Database.getConnection()` and then close it. Since they both use the same instance of the connection object if `Foo` closes, it will also be closed for `Bar`, right? – Christophe De Troyer Aug 18 '15 at 09:27
  • @ChristopheDeTroyer: *"Since they both use the **same instance** of the connection object"* Then your code is not implemented as per the answer (i.e. your connection object is thus indeed a static field of the class) and you will indeed run into major trouble this way (as indicated by the comment). – BalusC Aug 18 '15 at 09:28
  • The example given generates a new connection every time the static function getConnection is called. – Gilles Lesire Dec 11 '19 at 11:37
5

Below code is a working and tested Singleton Pattern for Java.

public class Database {

    private static Database dbIsntance;
    private static Connection con ;
    private static Statement stmt;


    private Database() {
      // private constructor //
    }

    public static Database getInstance(){
    if(dbIsntance==null){
        dbIsntance= new Database();
    }
    return dbIsntance;
    }

    public  Connection getConnection(){

        if(con==null){
            try {
                String host = "jdbc:derby://localhost:1527/yourdatabasename";
                String username = "yourusername";
                String password = "yourpassword";
                con = DriverManager.getConnection( host, username, password );
            } catch (SQLException ex) {
                Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        return con;
    }

While getting Connection in any Class simply use below line

Connection con = Database.getInstance().getConnection();

Hope it may help :)

farhangdon
  • 2,003
  • 2
  • 21
  • 30
4
package es.sm2.conexion;

    import java.sql.Connection;
    import java.sql.DriverManager;

    public class ConexionTest {
        private static Connection conn = null;

        static Connection getConnection() throws Exception {
            if (conn == null) {
                String url = "jdbc:mysql://localhost:3306/";
                String dbName = "test";
                String driver = "com.mysql.jdbc.Driver";
                String userName = "userparatest";
                String password = "userparatest";

                Class.forName(driver).newInstance();
                conn = DriverManager.getConnection(url + dbName, userName, password);
            }

            return conn;
        }
    }

To close Connection

public static void closeConnection(Connection conn) {

        try {

            conn.close();

        } catch (SQLException e) {

        }

    }

To call to the connection:

package conexion.uno;

import java.sql.*;

import es.sm2.conexion.ConexionTest;

public class LLamadorConexion {

    public void llamada() {
        Connection conn = null;
        PreparedStatement statement = null;
        ResultSet resultado = null;
        String query = "SELECT * FROM empleados";

        try {
            conn = ConexionTest.getConnection();
            statement = conn.prepareStatement(query);
            resultado = statement.executeQuery();

            while (resultado.next()) {
                System.out.println(resultado.getString(1) + "\t" + resultado.getString(2) + "\t" + resultado.getString(3) + "\t" );
            }
        } 
        catch (Exception e) {
            System.err.println("El porque del cascar: " + e.getMessage());
        } 
        finally {
            ConexionTest.closeConnection(conn);

        }
    }
}
Riyafa Abdul Hameed
  • 7,417
  • 6
  • 40
  • 55
PauRibes
  • 41
  • 4
1

Great post, farhangdon! I, however, found it a little troublesome because once you close the connection, you have no other way to start a new one. A little trick will solve it though:

Replace if(con==null) with if(con==null || con.isClosed())

Andrew
  • 26,706
  • 9
  • 85
  • 101
-1
import java.sql.Connection;
import java.sql.DriverManager;

public class sql11 {

    static Connection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/ics", "root", "077");
        return c;

    }
}
Frank Shearar
  • 17,012
  • 8
  • 67
  • 94