Как удалить список объектов/сущностей из базы данных комнат?

#java #android #android-room

Вопрос:

У меня была идея о том, как удалить один объект или удалить все объекты из базы данных комнат. Но я хочу удалить список объектов из базы данных комнат, но не нашел никакого решения.

Я пробовал эти коды, но они не работали.

 @Delete(entity = CollectionData.class)
void deleteList(List<CollectionData> collectionDataList);
 

и

 @Delete
void deleteList(List<CollectionData> collectionDataList);
 

ни один из этих кодов не работает. Любая помощь…

Комментарии:

1. Сейчас он работает идеально. Я не знаю, что случилось раньше. Но теперь он отлично работает после удаления и новой переустановки.

2. Что я делал неправильно, так это изменял список во время операции удаления, так как удаление выполнялось в фоновом потоке через службу исполнителя. Так что передача скопированного списка решила мою проблему. Создайте новый список : новый список ArrayList<>(listToBeDeleted)

Ответ №1:

То, что вы написали выше, должно сработать. вы можете ответить на следующие вопросы?

  1. являются ли данные сбора аннотированными с помощью @Entity?
  2. вы определили какой-либо первичный ключ для класса сущностей?
  3. при вызове этого метода удаления убедитесь, что передаваемый объект имеет этот первичный ключ.

вы также можете опубликовать свой класс сущностей?

В качестве обходного пути вы также можете сделать что-то вроде этого:

 @Query("delete from tableName where id in (:idList)")
fun deleteDataById(idList: List<Int>) 
 

Комментарии:

1. Эй, спасибо, что восстановили его работу сейчас.

Ответ №2:

С вами все в порядке, так что, вероятно, ваш список неверен. Одна из ловушек, в которую люди, как правило, попадают, — это использование объектов, которым не был присвоен первичный ключ со значением, присвоенным при создании этого первичного ключа при вставке.

 @PrimaryKey(autogenerate = true)
long the_variable_aka_columnname;
....
 
  • long может быть длинным, int, целым числом

Похожий вариант-это

 @PrimaryKey
Long the_variable_aka_columnname = null;
 
  • Длинное или целое число

Оба результата приводят к тому, что столбец является ЦЕЛОЧИСЛЕННЫМ ПЕРВИЧНЫМ КЛЮЧОМ, А НЕ НУЛЕВЫМ (первый имеет АВТОИНКРЕМЕНТ), что делает столбец псевдонимом идентификатора строки, и, следовательно, номер не будет указывать значения, и в результате значение будет присвоено.

Таким образом, объект, используемый для вставки, НЕ совпадает с результирующим столбцом и, следовательно, при использовании для удаления не приведет к удалению строк.

Я подозреваю, что это вполне может быть причиной того, что вы каким-то образом не извлекли значение @Primary Key.

Демонстрация

Данные коллекции @Entity :-

 @Entity
class CollectionData {
    @PrimaryKey
    Long id = null;
    String name;

    CollectionData(){}

    @Ignore
    CollectionData(String name) {
        this.name = name;
    }
}
 
  • столбцу идентификатора, если он специально не задан, будет присвоено значение, аналогичное значению autogenerate = true

Коллекция классов @Daoдатадао :-

 @Dao
abstract class CollectionDataDao {
    @Insert
    abstract long[] insert(ArrayList<CollectionData> collectionDataArrayList);
    @Delete
    abstract int delete(List<CollectionData> collectionDataList);
    @Query("SELECT * FROM collectiondata WHERE name LIKE :preWildChar||:nameSelection||:postWildChar")
    abstract List<CollectionData> getByName(String preWildChar, String nameSelection, String postWildChar);
    @Query("DELETE FROM collectiondata")
    abstract int deleteAll();
}
 

Довольно стандартный класс @Database, поэтому включать его не нужно (для удобства и краткости .allowManThreadQueries было использовано примечание).

И некоторый код в действии, который получает базу данных и dao, а затем :-

  • удаляет все существующие данные (для удобства повторного запуска)
  • создает массив данных коллекции (4)
  • вставляет их (получение списка идентификаторов)
  • выписывает список удостоверений личности
  • записывает список массивов, т. е. все идентификаторы равны нулю
  • удаляет в соответствии с ArrayList, записывая количество удалений
    • 0, так как нет строк с идентификатором null
  • удаляет в соответствии со списком, полученным из базы данных (с соответствующими идентификаторами), записывая номер удаленного
    • 2 УДАЛЕНО, так как идентификаторы соответствуют тому, что есть в базе данных
  • изменяет исходный список массивов, изменяя имя на то, что не хранится, и изменяя идентификатор на соответствующий идентификатор с помощью вставленного идентификатора.
  • удаляет в соответствии с измененным исходным списком и записывает номер удален.
    • остальные 2. То есть 2 из 4 вставленных были удалены выше, так что 2 совпадают.
    • изменение имени показывает, что важным значением является идентификатор (первичный ключ), который используется только для определения того, что удаляется.
    • по сути, комната строит SQL DELETE FROM the_table WHERE the_primary_key IN (the_list_of_primary_key_values_from_the_list_of_objects);

Код такой :-

     db = TheDatabase.getInstance(this);
    daoCollectionData = db.getCollectionDataDao();
    daoCollectionData.deleteAll();
    ArrayList<CollectionData> cdl = new ArrayList();
    cdl.add(new CollectionData("CD001"));
    cdl.add(new CollectionData("CD002"));
    cdl.add(new CollectionData("CD003"));
    cdl.add(new CollectionData("CD0030"));
    /* Insert the Collection Datas  getting the IDs*/
    long[] insertedIdList = daoCollectionData.insert(cdl);
    /* Show the IDs (write to the log) */
    for(long l: insertedIdList) {
        Log.d("CDINFO","Insert ID = "   l);
    }
    /* The the original Collection Datas (null ID's) */
    for(CollectionData cd: cdl) {
        Log.d("CDINFO","Name = "   cd.name   " ID = "   cd.id);
    }
    /* DELETE according to original list. Note will not delete because IDs have not been set don't match */
    Log.d("CDINFO","CollectionData's deleted = "   daoCollectionData.delete(cdl));
    /* Extract some and delete (any with a 3 in the name)*/
    List<CollectionData> deleteList = daoCollectionData.getByName("%","3","%");
    Log.d("CDINFO"," CollectionData's deleted = "   daoCollectionData.delete(deleteList));
    /* alter the cdl list to set the ids */
    for (int i=0; i < insertedIdList.length; i  ) {
        CollectionData replace = cdl.get(i);
        replace.id = insertedIdList[i];
        replace.name = "not the original name";
        cdl.set(i,replace);
    }
    /* Show the altered original list */
    for(CollectionData cd: cdl) {
        Log.d("CDINFO","Name = "   cd.name   " ID = "   cd.id);
    }
    /* and delete them */
    Log.d("CDINFO","CollectionData's deleted = "   daoCollectionData.delete(cdl));
 

Вывод в журнал будет :-

 2021-10-18 22:37:18.295 D/CDINFO: Insert ID = 1
2021-10-18 22:37:18.295 D/CDINFO: Insert ID = 2
2021-10-18 22:37:18.295 D/CDINFO: Insert ID = 3
2021-10-18 22:37:18.295 D/CDINFO: Insert ID = 4
2021-10-18 22:37:18.295 D/CDINFO: Name = CD001 ID = null
2021-10-18 22:37:18.295 D/CDINFO: Name = CD002 ID = null
2021-10-18 22:37:18.295 D/CDINFO: Name = CD003 ID = null
2021-10-18 22:37:18.295 D/CDINFO: Name = CD0030 ID = null
2021-10-18 22:37:18.303 D/CDINFO: CollectionData's deleted = 0
2021-10-18 22:37:18.308 D/CDINFO:  CollectionData's deleted = 2
2021-10-18 22:37:18.308 D/CDINFO: Name = not the original name ID = 1
2021-10-18 22:37:18.308 D/CDINFO: Name = not the original name ID = 2
2021-10-18 22:37:18.308 D/CDINFO: Name = not the original name ID = 3
2021-10-18 22:37:18.308 D/CDINFO: Name = not the original name ID = 4
2021-10-18 22:37:18.311 D/CDINFO: CollectionData's deleted = 2
 
  • Возможно, вы захотите адаптировать код для записи ваших данных в журнал, что может помочь определить, что не так со списком, который вы передаете.