My class derived from SQLiteOpenHelper is getting huge

后端 未结 5 1074
遥遥无期
遥遥无期 2021-02-19 07:55

My class derived from SQLiteOpenHelper is getting bigger and bigger over a time. At the speaking time it is more than 1500 lines of code which is not considered to

相关标签:
5条回答
  • 2021-02-19 08:17

    I follow as given code snippet:

    SQLHelper class:

        public class SQLHelper extends SQLiteOpenHelper {
            public SQLHelper(Context context, String DBName) 
            {
                super(context, DBName, null, DATABASE_VERSION);
            }
    
            public SQLiteDatabase getDBObject(int isWrtitable) 
            {
                return (isWrtitable == 1) ? this.getWritableDatabase() : this.getReadableDatabase();
            }
    
            @Override
            public void onOpen(SQLiteDatabase db) 
            {
                super.onOpen(db);
                onCreate(db);
            }
    
            @Override
            public void onCreate(SQLiteDatabase db) 
            {
    
                db.execSQL(TABLE_1);
                db.execSQL(TABLE_2);
                ...
                db.execSQL(TABLE_N);
            }
        }
    

    MySQLManager: Which does most of the work:

        public class MySQLManager 
        {
            private SQLHelper sqlHelper;
    
            //Singlton class
    
            public void initMySQLManager(Context context, String DBName) 
            {
                _context = context;
                sqlHelper = new DBHandler(context, DBName);
            }
    
    
            public MyObject getMyObjectRecord() {
                MyObject myObj = new MyObject();
                Cursor cursor = null;
    
                try {
                    cursor = dbObject.getWritableDatabase().rawQuery("select *  FROM " + SQLHelper.MYOBJECT_TABLE + ";", null);
                    //fetch things
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (cursor != null && !cursor.isClosed()) {
                        cursor.close();
                    }
                }
                return bookVo;
            }
    
            //Similarly other methods.
        }
    
    0 讨论(0)
  • 2021-02-19 08:25

    You may consider a singleton class to only open and close db connection (or catch, release like a pool) then executing the db operations with command class like in command pattern

    And you can use facade pattern to merge this commands in an execute order for more complex database operations.This will make your code clean and easy to control. like when you change your InsertBookCommand class, all related operations will change behavior due to it.

    To sum up, my solution is:

    Open db connection and pass the db as parameter to commands. then execute the commands.

    0 讨论(0)
  • 2021-02-19 08:29

    Yes, the examples shown in the dev. site do encourage the creation of a monster class where you hardcode the names of every table and column. This is a mess. You might want to create a class to handle each table. These classes can act as Data Access Objects for each table.

    This is what I use:

        public interface DataAccessObject<E> {
    
            public void onCreate(SQLiteDatabase db);
    
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
    
            public void create(E... params);
    
            public E[] retrieve(E... params);
    
            public void update(E... params);
    
            public void delete(E... params);
    
        }
    

    Then I code an implementation for each table. The generic tipe E are usually pojos. Notice I'm not mixing the classes intended to just hold data (pojos) with the classes in charge of persisting-retrieving data (DAO's). For instance a pojo could be Car, with its variables (color, year, etc). Then i'd code a CarDAO extending DataAccessObject<Car>. And this DAO class is in charge of mapping the pojo's variables to DB columns, querying the table and writting to it.

    Finally, you can have a SQLiteOpenHelper that is injected with the DAOs, and delegates stuff for each table to them. These DAO implementations are the ones having table and column name constants. And they can talk to each other if needed for some complex queries. (Notice how this is also one of the drawbacks of this approach: producing a neat design is not straightforward when you need queries involving many tables and columns).

    0 讨论(0)
  • 2021-02-19 08:32

    You should avoid putting all model specific code in your helper as you can. Think about it as something you could be able to reuse as much as you can in the next project. You can follow some of the common Data Abstraction patterns and principles you will see around.

    • For example, you can think about Active Record , where you have your business objects, with its fields and methods, and also all the method related to the persistance (read and write from database).
    • Also, you can think about a lightweight object, and save instances into and retrieve them from the database by some other object which gives mapping capabilities, such an entity manager, like some ORMs do.
    • You can also take a look a Zend TableGateway that its a cool approach to representing database tables as objects, that you an migrate to android and sqlite.
    • You can use a simple and yet powerful solution based on hydrators, as I explain below

    Personally, what i prefer is to use Hydrators

    This is a concept widely used in some ORM, also in native Zend Framework, and in other systems to provide data persistence, this is, to help objects or even web forms to be mapped to database records in an easy to understand and to maintain way.

    A hydrator is an object that maps the database field names on one side, to the entity properties on the other. It doesn’t store this information internally, but provides mechanisms both for creating objects from databases, as well as extracting datasets from objects to update the database.
    Is something that can start as easy as an object with an array of Column Names -> Entity Properties, and when its YourClass hydrate() method is called, will transfer the respective information from the datasource to the model object, and when the extract(YourClass yourObject) method is called, it transfer the data contained in yourObject to the corresponding database record

    I like this approach a lot, since it is really easy to create an Interface, and several implementations for common use cases. So you can perform changes in your database without affecting the main objects, or the helper. Also, using the same interface, you can create mappers to exports your data to json, xml, rest calls, or whatever other stuff you can imagine.

    If you can think about a good hydrator desing, and then create some classes to inherit from, you can have a really small databasehelper, really small entity objects, some abstract classes doing common work, and some concrete hydrators that can get all the weight you could need, but never that much since you can have one for every table or object type, so the classes are obviusly smaller, and moreover, they only contains code that is related at a business level.

    0 讨论(0)
  • 2021-02-19 08:36

    Your helper should not need to be that size. I can only assume you are putting all code that manipulates data into your Helper.

    You should put code in the class to which it relates and where you can access it in an object oriented way.

    e.g If you have a Contacts class. You would put code that saved a contact to the database in it.

    See my post here

    0 讨论(0)
提交回复
热议问题