#java #android #android-room
Вопрос:
У меня была идея о том, как удалить один объект или удалить все объекты из базы данных комнат. Но я хочу удалить список объектов из базы данных комнат, но не нашел никакого решения.
Я пробовал эти коды, но они не работали.
@Delete(entity = CollectionData.class)
void deleteList(List<CollectionData> collectionDataList);
и
@Delete
void deleteList(List<CollectionData> collectionDataList);
ни один из этих кодов не работает. Любая помощь…
Комментарии:
1. Сейчас он работает идеально. Я не знаю, что случилось раньше. Но теперь он отлично работает после удаления и новой переустановки.
2. Что я делал неправильно, так это изменял список во время операции удаления, так как удаление выполнялось в фоновом потоке через службу исполнителя. Так что передача скопированного списка решила мою проблему. Создайте новый список : новый список ArrayList<>(listToBeDeleted)
Ответ №1:
То, что вы написали выше, должно сработать. вы можете ответить на следующие вопросы?
- являются ли данные сбора аннотированными с помощью @Entity?
- вы определили какой-либо первичный ключ для класса сущностей?
- при вызове этого метода удаления убедитесь, что передаваемый объект имеет этот первичный ключ.
вы также можете опубликовать свой класс сущностей?
В качестве обходного пути вы также можете сделать что-то вроде этого:
@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
- Возможно, вы захотите адаптировать код для записи ваших данных в журнал, что может помочь определить, что не так со списком, который вы передаете.