I have a class that provides methods for working with a database, and this is the only class that works with the database in the program:

public class ForwardersHelper { private DBHelper dbHelper; private SQLiteDatabase db; ... ... ... public void addForwarder(Forwarder forwarder) { ... ... ... } public void deleteForwarder(int forwarderId) { ... ... ... } public void changeForwarder(Forwarder forwarder) { ... ... ... } public ArrayList<Forwarder> getForwardersList() { ... ... ... } public int getFreeForwarderId() { ... ... ... } } 

I have two options for initializing the connection to the database: make everything static and access the class without instances or open the connection, using appropriate methods:


Option 1:

  public class ForwardersHelper { private static DBHelper dbHelper; private static SQLiteDatabase db; public static void init(Context context) { dbHelper = new DBHelper(context); db = dbHelper.getWritableDatabase(); } @Override //Во время уничтожения объекта уборщиком мусора, закроются все подключения, так //как этот метод вызывается автоматически public void finalize() { db.close(); dbHelper.close(); try { super.finalize(); } catch (Throwable e) { e.printStackTrace(); } } ... ... ... } 

When starting the program in the activity or Application class, call the ForwardersHelper.init(this) method. Since static methods are initialized once and for all, such a call will open a connection to the database and work with the methods will be available throughout the program.


Option 2:

 public class ForwardersHelper { private DBHelper dbHelper; private SQLiteDatabase db; public void openDBConnection(Context context) { dbHelper = new DBHelper(context); db = dbHelper.getWritableDatabase(); } public void closeDBConnection(Context context) { db.close(); dbHelper.close(); } ... ... ... } 

Then, after creating each instance, call openDBConnection() , and after using it, call closeDBConnection() .


I tend to the first option, because it is more convenient to use, less code will be obtained in other classes and the code will be clearer, but the code will become a little more difficult to understand and I have doubts about the correctness of finalize() . The second option is clearer for those who read it, but it will become a bit more and lose expressiveness. Which option will still be more correct and why?

    2 answers 2

    From my point of view, both of your options are not correct. For good, most of your classes that you create should not be aware that there is a context, an activity or a fragment. This will reduce the coherence of the code, as well as in the future will simplify testing, refactoring and in which case the code can be easily transferred to a separate module. Also, when writing code, it is better to use the principle of dependency injection (DI). Those. the class, in your case ForwardersHelper , should not itself create a SQLiteDatabase object, but should receive it through a constructor, a special method, or something else, but the main thing is that it should not create it itself. This will easily allow, if necessary, to substitute the implementation of dependencies, which will also facilitate the expansion of the code, testing the code and allow you to easily implement any library for DI.

    Based on the above, my ForwardersHelper class would look like this.

     public class ForwardersHelper { private final DBHelper dbHelper; private final SQLiteDatabase db; public ForwardersHelper(DBHelper dbHelper, SQLiteDatabase db){ this.dbHelper = dbHelper; this.db = db; } // Остальной код } 

    If you want a Singleton, you can do this:

     public class ForwardersHelper { private static final ForwardersHelper INSTANCE = new ForwardersHelper(); private DBHelper dbHelper; private SQLiteDatabase db; public static ForwardersHelper getInstance(){ return INSTANCE; } private ForwardersHelper(){ } public void init(DBHelper dbHelper, SQLiteDatabase db){ this.dbHelper = dbHelper; this.db = db; } // Остальной код } 

    We initialize once into Application.onCreate() and then use it as we want.

    In which case, such code can be quickly rewritten using Dagger2 .

    There is no need to close the database manually. The connection closes when the system kills the application. Read more here .

    • And what's the point of excluding the creation of a specific database from a class if its implementation is “sharpened” to interact specifically with this database? - user189127
    • @ bukashka101 the point is that the class does not know where to get the base from. Your class for working with a database should know only how to work with it, and not how to create it or where to get it from. It will also facilitate the testing of a sample from the database, since it is easy to slip the test ready, about which you will know how many and what objects there are. - temq
    • I don’t understand a little what is easier. The class does not create a base, but reads it! And what is the difference between the base stand in the classroom and from the outside, the code will be the same? - user189127
    • @ bukashka101 in your case, the class itself decides where to get the base from, although it should only read it. Plus, you tie it to the context, which is also not very good. The less the class knows about the environment, the easier it will later be to expand, change, test. - temq
    • That is the point is that I did not give him the context, but only the base in order to then change the behavior of the class with this database? - user189127

    use singleton to initialize the database connection object.

    Within each method, call

     db.getInstance() // а дальше работаете 

    Singleton allows you to get an object such that if it is not initialized, it will first initialize and return

     SQLiteDatabase getInstance() { if(db == null){ db = new .... db.connect(); }else{ if(!db.isConnected()) {db.connect()} retetn db; } 

    This simplifies the life and readability of the code.

    • Then there is one "but" - I need to transfer the context, that is, either initialize or create at least one object that initializes the static database variable. - user189127
    • so it simplifies the singleton. you initialize once and forget about it - Senior Pomidor
    • Hmm ... Indeed, a good way out of the situation. But nevertheless, this class needs to be received every time, whereas the static version can be accessed immediately and directly and, similarly to the static version, it will have to close the connection through finalizе() , and I’m worried about whether to use the variant with finaliza() or without it, and why, and it is also worth keeping the database open or better, after a one-time use, close the connection. - user189127
    • The connection will close automatically when the program ends. leave it open better, as the connection will take seconds. 3. If you access the database many times, then leave it open. In my project for 6h the connection is open and everything works normally. - Senior Pomidor
    • 3 seconds? : What about so much? I do not have a second! - user189127