Мой класс, полученный из SQLiteOpenHelper, становится огромным

Мой класс, полученный из SQLiteOpenHelper, становится все больше и больше за время. В разное время это более 1500 строк кода, который не считается прохладным. Может быть какое-то изящное решение, чтобы предотвратить его рост, т.е. Разделение на части. Не уверен, что это такое. Некоторые люди говорят, что это плохая практика, чтобы наследовать от упомянутого класса, потому что это приводит к неправильному поведению к процедурам создания/обновления базы данных. Любой намек? Большое спасибо!

Ответы

Ответ 1

Да, примеры, показанные в dev. сайт поощряют создание класса монстров, где вы жестко указываете имена каждой таблицы и столбца. Это беспорядок. Возможно, вы захотите создать класс для обработки каждой таблицы. Эти классы могут действовать как Объекты доступа к данным для каждой таблицы.

Это то, что я использую:

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

    }

Затем я кодирую реализацию для каждой таблицы. Типичным типом E обычно являются pojos. Заметьте, что я не смешиваю классы, предназначенные только для хранения данных (pojos) с классами, ответственными за сохраняющие данные (DAO's). Например, pojo может быть Car, с его переменными (цвет, год и т.д.). Тогда я бы закодировал carDAO, расширяющий DataAccessObject<Car>. И этот класс DAO отвечает за сопоставление переменных pojo с столбцами DB, запрос к таблице и запись на нее.

Наконец, вы можете иметь SQLiteOpenHelper, который вводится DAO, и делегирует материал для каждой таблицы. Эти реализации DAO - это те, у которых есть константы имен таблиц и столбцов. И они могут разговаривать друг с другом, если это необходимо для некоторых сложных запросов. (Обратите внимание, что это также является одним из недостатков этого подхода: создание аккуратного дизайна не является простым, когда вам нужны запросы, содержащие множество таблиц и столбцов).

Ответ 2

Вы должны избегать размещения всего конкретного кода модели в своем помощнике, как можете. Подумайте об этом как о чем-то, что вы могли бы использовать, как можете в следующем проекте. Вы можете следовать некоторым из общих шаблонов и принципов абстракции данных, которые вы увидите вокруг.

  • Например, вы можете думать о Active Record, где у вас есть ваши бизнес-объекты с его полями и методами, а также весь метод связанные с устойчивостью (чтение и запись из базы данных).
  • Кроме того, вы можете думать о легком объекте и сохранять экземпляры и извлекать их из базы данных каким-либо другим объектом, который предоставляет возможности отображения, такой менеджер сущностей, как и некоторые ORM.
  • Вы также можете взглянуть на Zend TableGateway, что его классный подход к представлению таблиц базы данных как объектов, которые вы переносите на Android и SQLite.
  • Вы можете использовать простое и вместе с тем мощное решение на основе гидраторов, как я объясняю ниже.

Лично я предпочитаю использовать Гидраторы

Это концепция, широко используемая в некоторых ORM, также в родной Zend Framework и в других системах для обеспечения непрерывности данных, то есть для того, чтобы помочь объектам или даже веб-формам сопоставляться с записями базы данных в удобном для понимания и для поддержания пути.

Гидратор - это объект, который сопоставляет имена полей базы данных с одной стороны, свойствам объекта на другом. Он не хранит эту информацию внутренне, но предоставляет механизмы как для создания объектов из баз данных, так и для извлечения наборов данных из объектов для обновления базы данных.
Это то, что можно начинать так же просто, как объект с массивом имен столбцов → Свойства сущностей и когда его метод YourClass hydrate() вызывается, передаст соответствующую информацию из источника данных объекту модели, а когда extract(YourClass yourObject) метод, он переносит данные, содержащиеся в вашем объекте, в соответствующую запись базы данных

Мне очень нравится этот подход, поскольку очень просто создать интерфейс и несколько реализаций для случаев общего использования. Таким образом, вы можете выполнять изменения в своей базе данных, не затрагивая основные объекты или помощник. Кроме того, используя тот же интерфейс, , вы можете создавать карты для экспорта ваших данных в json, xml, rest calls или любой другой материал, который вы можете себе представить.

Если вы можете подумать о хорошем гидраторе, а затем создать некоторые классы для наследования, у вас может быть действительно небольшой базовый сервер базы данных, очень маленькие объекты сущности, некоторые абстрактные классы, выполняющие общую работу, и некоторые конкретные гидраторы, которые могут получить все вес, который вам может понадобиться, но никогда не так много, поскольку вы можете иметь один для каждого типа таблицы или объекта, поэтому классы кажутся меньше, и, кроме того, они содержат только код, который связан с бизнес-уровнем.

Ответ 3

Ваш помощник не должен быть такого размера. Я могу только предположить, что вы помещаете весь код, который манипулирует данными в ваш помощник.

Вы должны поместить код в класс, к которому он относится, и где вы можете получить к нему доступ объектно-ориентированным способом.

Например, если у вас есть класс "Контакты". Вы бы поставили код, который сохранил контакт с базой данных в нем.

Смотрите мой пост здесь

Ответ 4

Я следую приведенному фрагменту кода:

Класс SQLHelper:

    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: который выполняет большую часть работы:

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

Ответ 5

Вы можете рассматривать одноэлементный класс только для открытия и закрытия соединения db (или catch, release, как пул), а затем выполнения операций db с помощью командного класса, например, в шаблон команды

И вы можете использовать фасадную схему, чтобы объединить эти команды в порядке выполнения для более сложных операций с базой данных. Это сделает ваш код чистым и легким контролировать. например, когда вы меняете свой класс InsertBookCommand, все связанные с ним операции изменят поведение из-за него.

Подводя итог, мое решение:

Откройте соединение db и передайте команду db как параметры в команды. затем выполните команды.