Android: ContentProvider для каждой таблицы/обработки отношений "один ко многим"

При использовании поставщика контента для доступа к базе данных SQLite

  • Лучше ли вам иметь поставщика контента для каждой таблицы или использовать его для всех таблиц?
  • Как обрабатывать отношения "один ко многим" при создании новых записей?

Ответ 1

ContentProvider не является базой данных

ContentProvider - это способ публичного (или полупубличного) доступа к данным в качестве контента. Это можно сделать несколькими способами: через доступ к файлам, SQLite или даже доступ к сети. ContentProvider сам по себе не является базой данных, но вы можете запрограммировать для нее базу данных. У вас также может быть несколько ContentProviders, которые обращаются к одной и той же базе данных, но распределяют разные уровни доступа или же содержимое по-разному в зависимости от запрашивающего.

То, что вы действительно спрашиваете, не является вопросом ContentProvider, а вопросом базы данных "Как обрабатывать отношения в базе данных SQLite", потому что ContentProvider не использует код базы данных, если вы не скажете его через SQLiteOpenHelper и другие аналогичные классы. Таким образом, вам просто нужно запрограммировать доступ к базе данных правильно, и ваша база данных SQLite будет работать по желанию.

База данных - это база данных

В старые времена базы данных были просто плоскими файлами, где каждая таблица часто являлась своей собственной сущностью, чтобы обеспечить рост. Теперь, с СУБД, есть очень мало оснований для этого. SQLite подобен любой другой платформе базы данных в этом отношении и может содержать столько таблиц, сколько у вас есть места для их хранения.

SQLite

Существуют некоторые функции, которые SQLite хорошо обрабатывает, некоторые из них обрабатываются - но не очень хорошо, а некоторые - вообще не обрабатываются. Отношения - это одна из тех вещей, которые были исключены из некоторых версий Android SQLite, поскольку она поставляется без поддержки внешнего ключа. Это была очень запрошенная функция, и она была добавлена ​​в SQLite 3.6.22, которая не отправлялась до Android 2.2. Тем не менее, все еще есть много сообщений об ошибках, но в самых ранних воплощениях.

Android pre 2.2

К счастью, будучи совместимым с SQL и простой СУБД (а не RDBMS в это время), есть несколько простых способов обойти это, в конце концов, внешний ключ - это просто поле в другой таблице.

  • Вы можете применять операторы базы данных INSERT и UPDATE, создавая CONSTRAINT, когда используете оператор CREATE TABLE.
  • Вы можете запросить другую таблицу для соответствующего _id, чтобы получить свой внешний ключ.
  • Вы можете запросить исходную таблицу любым подходящим оператором SELECT, используя INNER JOIN, тем самым обеспечив псевдосвязь.

Так как версия SQLite SQLite не обеспечивает прямое взаимодействие, если вы хотите CASCADE ON DELETE, вам придется делать это вручную. Но это можно сделать с помощью другого простого оператора SQL. Я по существу написал свою собственную библиотеку, чтобы обеспечить соблюдение таких отношений, поскольку все это нужно делать вручную. Однако я должен сказать, что эффективность SQLite и SQL в целом делает это очень быстрым и легким.

По сути, процесс для любого принудительного отношения выглядит следующим образом:

  • В запросе, который требует внешний ключ, используйте JOIN.
  • В INSERT используйте CONSTRAINT в поле внешнего ключа NOT NULL
  • В поле UPDATE в поле первичного ключа, являющемся внешним ключом в другом TABLE, запустите второй UPDATE в соответствующем TABLE, который имеет внешний ключ. (ОБНОВЛЕНИЕ КАСКАДА)
  • Для DELETE с теми же параметрами выполните еще один DELETE, где foreign_key = _id (убедитесь, что вы сначала получили _id перед тем, как DELETE строка).

Android 2.2 +

Внешние ключи поддерживаются, но по умолчанию отключены. Сначала вы должны включить их:

db.execSQL("PRAGMA foreign_keys=ON;");

Затем вам нужно создать связь TRIGGER. Это делается при создании TABLE, а не отдельного оператора TRIGGER. См. Ниже:

// Added at the end of CREATE TABLE statement in the MANY table
FOREIGN KEY(foreign_key_name) REFERENCES one_table_name(primary_key_name)

Для получения дополнительной информации о SQLite и его возможностях посетите официальный сайт SQLite. Это важно, поскольку у вас нет всех JOIN, которые вы делаете в других СУБД. Для получения конкретной информации о классах SQLite в Android читайте документацию.

Ответ 2

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

Ответ 3

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

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