Мой вопрос: как я могу удалить все записи в базе данных и перезапустить автоматически сгенерированные первичные ключи с 0 при переустановке приложения в студии Android? В настоящее время я пытаюсь использовать базу данных Room для личного проекта и уже обнаружил, что методы Dao, аннотированные @Insert, возвращают Long или Array of Longs. Насколько мне известно, этот Long представляет собой первичный ключ вставленной записи. Мне еще не удалось заставить работать методы get, поэтому я не могу видеть в пользовательском интерфейсе элементы таблицы, но я проверяю с помощью простой printlns() значения, возвращаемые вставками, и они продолжают увеличиваться даже после переустановки и перезапуска приложение. Я тоже уже читал о
android:allowBackup = "false"
свойство в файле манифеста. Поэтому я установил для него значение false, как было предложено в сообщении о stackoverflow, но, по-видимому, это бесполезно, потому что значение, возвращаемое вставкой, продолжает увеличиваться. Таким образом, может быть два сценария: либо записи не удаляются, хотя я установил для этого свойства значение false, либо они удаляются, но первичный ключ не сбрасывается, и в этом случае мне все равно хотелось бы знать, как его сбросить.
Длинное значение, возвращаемое вставкой
Я добавил выше ссылку, включающую некоторые мои поисковые запросы. Я собираюсь отредактировать и добавить больше, если найду что-то еще. Любой совет будет высоко оценен.
Когда вы используете autoGenerate=True, это фактически не включает генерацию значения. Вместо этого вводится ограничение AUTOINCREMENT.
Это ограничение (правило) гласит, что сгенерированное значение ДОЛЖНО быть больше, чем любое использованное, независимо от того, существует ли еще соответствующая строка. Это делается путем сохранения самого последнего сгенерированного значения (самого высокого значения) в таблице sqlite_sequence, в которой есть по одной строке на таблицу, и, следовательно, как оно сохраняет самое высокое/самое большое сгенерированное значение.
Одним из вариантов может быть сброс или удаление соответствующего значения в таблице sqlite_sequence (не рекомендуется манипулировать системными таблицами).
Другой вариант — не указывать autoGenerate=true, указав autoGenerate=false или, поскольку false, по умолчанию код отсутствует. Однако Room обрабатывает это поле по-другому.
Обычно у вас будет: -
@PrimaryKey(autoGenerate='true')
val id: Long=0, ....
Room, когда autoGenerate имеет значение true, принимает 0, чтобы не представлять никакого конкретного значения, и, следовательно, базовый код вставки не предоставляет значение, и, следовательно, значение генерируется.
Тот же код, но если autoGenerate имеет значение false, значением, которое будет использоваться, считается 0, и это значение не будет сгенерировано.
Если код изменен на: -
@PrimaryKey
val id:Long=null, ....
Затем, если не указывать значение, во вставку передается значение null, и sqlite (в особом случае столбца типа INTEGER, который является первичным ключом) генерирует значение.
Генерация значения с помощью AUTOINCREMENT (autoGenerate=true) основана на 1 + наибольшем из наибольшего значения в фактической таблице (столбец id) и значения, сохраненного для таблицы в sqlite_seqeunce (наибольшее из когда-либо выделенных значений).
Генерация значения без AUTOINCREMENT — это просто 1 + наибольшее значение в фактической таблице (которое равно 0, если в таблице нет строк).
Однако цель такого столбца состоит в том, чтобы однозначно идентифицировать строку, используя значение для других целей, например, ожидая, что монотонно увеличивающееся число (например, 1,2,3,4,5...) скорее всего приведет к к вопросам.
Демо
Рассмотрим следующие два класса (на основе вышеизложенного):
@Entity
data class AutoIncrementId(
@PrimaryKey(autoGenerate = true)
val id: Long=0
)
@Entity
data class GeneratedId(
@PrimaryKey
val id: Long?=null
)
Теперь следующие функции (в аннотированном интерфейсе @Dao под названием AllDAOs):
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(autoIncrementId: AutoIncrementId): Long
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(generatedId: GeneratedId): Long
@Query("DELETE FROM autoincrementid")
fun emptyAutoGeneratedId(): Int
@Query("DELETE FROM generatedid")
fun emptyGeneratedId(): Int
@Query("UPDATE sqlite_sequence SET seq=0 /* WARNING RESETS FOR ALL TABLES */")
fun resetAutoGeneratedSequences(): Int
А затем следующий код активности: -
db = TheDatabase.getInstance(this)
dao = db.getAllDAOs()
dao.insert(AutoIncrementId())
dao.insert(GeneratedId())
dao.insert(AutoIncrementId())
dao.insert(GeneratedId())
/* Set id as 100 */
dao.insert(AutoIncrementId(100))
dao.insert(GeneratedId(100))
dao.emptyAutoGeneratedId()
dao.emptyGeneratedId()
dao.insert(AutoIncrementId())
dao.insert(GeneratedId())
Как видно, все действия выполняются парами (с автогенерацией и без).
Первоначально вставляются две строки с сгенерированными идентификаторами (две строки, скорее всего, будут иметь идентификаторы 1 и 2).
Следующие две строки вставляются с идентификатором, специально установленным на 100. Далее ВСЕ строки будут удалены.
Наконец, в каждый из них вставляется строка, в результате чего:
и :-
Как видно, таблица AutoIncrementId (autoGenerate=true) имеет идентификатор 101, хотя все остальные строки были удалены до вставки строки.
Однако таблица GeneratedId имеет идентификатор 1.
Обратите внимание, что в вашем вопросе в качестве начала указано 0. SQLite НЕ БУДЕТ генерировать значение идентификатора 0.
Сброс sqlite_sequence
Если dao.resetAutoGeneratedSequences() добавляется после вставок с идентификатором 100 и перед двумя последними вставками, то в результате оба значения идентификатора равны 1.
Вы можете обратиться к https://www.sqlite.org/autoinc.html, который расширяет вышеизложенное. Следует отметить, что использование AUTOINCREMENT не рекомендуется, поскольку его использование в большинстве случаев приводит к ненужной неэффективности.
Хорошо. Итак, я нахожу все ответы действительно полезными, но на самом деле я думаю, что проблема заключалась в том, что после погружения в ответы stackoverflow на ошибки и переустановки Android Studio, а также SDK, проблема заключалась в том, что если вы запускаете приложение непосредственно на своем мобильном устройстве, оно не запускается. на самом деле действительно переустановите приложение. Чтобы переустановить его, вам необходимо вручную удалить уже существующее приложение, а затем перезапустить его. После этого счетчик был сброшен на 1, поскольку данные приложения были удалены. Я почему-то считал, что удаление выполняется автоматически, но, как я уже сказал, сообщение об ошибке указало мне, что после переустановки IDE и SDK, если я хочу перезапустить приложение, мне нужно сначала удалить уже существующее, потому что, хотя они имеют одинаковое имя у них разные подписи. Я никогда раньше не встречал этого сообщения.
Это руководство, но может как-то помочь ✓Откройте информацию/детали «приложения» либо на AVD, либо на физическом устройстве (настройки>>«приложение»>>очистить данные/очистить хранилище). ✓Очистить данные (включая базы данных, имена пользователей, настройки приложений и т. д.) ✓Все будет сброшено, и первичный ключ начнется с 1. ✓Имейте в виду, что все ваши базы данных будут удалены!
Вы можете видеть элементы в базе данных. Используйте «Проверку приложений» в студии Android.