Room. Insert, Update, Delete, Transaction
У цьому уроці розглянемо докладніше анотації Insert, Update і Delete. А також дізнаємося, як використовувати транзакції в Room.
Insert
Анотація Insert - це простий спосіб вставити об'єкт у базу даних. Ми вже використовували її в прикладах минулих уроків.
Використання цієї анотації виглядає так:
@Dao
public interface EmployeeDao {
@Insert
void insert(Employee employee);
// ...
}
У Dao інтерфейсі описуємо метод, який на вхід приймає Entity об'єкт. До методу додаємо анотацію Insert і Room згенерує необхідний код у реалізації цього інтерфейсу.
Давайте подивимося, які ще можливості в нас є.
Вставка кількох об'єктів
Ми можемо передавати в метод не один, а кілька об'єктів, використовуючи varargs
@Insert
void insertMany(Employee... employees);
Також, це може бути список:
@Insert
void insert(List<Employee> employees);
Або це взагалі може бути будь-який Iterable:
@Insert
void insert(Iterable<Employee> employees);
При виклику цього методу ви можете використовувати масив або колекцію.
Отримання id
Під час вставки метод Insert може повертати id щойно доданого запису. Для цього треба описати метод так, щоб він повертав long.
@Insert
long insert(Employee employee);
Якщо в Employee є числовий первинний ключ, то саме його значення ви й отримаєте.
У разі додавання декількох записів, необхідно використовувати long[]
@Insert
long[] insert(List<Employee> employees);
або List<Long>
@Insert
List<Long> insert(List<Employee> employees);
Режими вставки
Розглянемо ситуацію, коли ми вставляємо в таблицю запис, але виявляється, що запис із таким ключем там уже є. За замовчуванням ми отримаємо помилку: SQLiteConstraintException: UNIQUE constraint failed. І нічого в базу не запишеться.
Але це можна змінити за допомогою параметра onConflict.
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Employee employee);
У режимі REPLACE старий запис буде замінено новим. Цей режим добре підходить, якщо вам треба вставити запис, якщо його ще немає в таблиці або оновити запис, якщо він уже є.
Також є режим IGNORE. У цьому режимі буде залишено старий запис і операція вставки не буде виконана.
Update
Ця анотація аналогічна Insert, але вона не вставляє, а оновлює об'єкти в бд.
@Update
void update(Employee employee);
Так само, як і з Insert, ми можемо використовувати колекції та varargs, щоб оновлювати кілька об'єктів одразу.
Update шукає в бд запис за ключем. Якщо не знайде, то нічого не станеться. Якщо знайде, то оновить усі поля, а не тільки ті, які ми заповнили в Entity об'єкті.
Ми можемо отримати кількість оновлених записів. Для цього опишіть метод так, щоб він повертав int.
@Update
int update(List<Employee> employee);
Як і Insert, Update підтримує параметр onConflict.
Delete
Методи з анотацією Delete видалятимуть об'єкти.
@Delete
void delete(Employee employee);
У Delete методах ми також можемо використовувати колекції та varargs, щоб видаляти кілька об'єктів одразу.
Delete шукає в бд запис за ключем.
Ми можемо отримати кількість видалених записів. Для цього необхідно описати метод так, щоб він повертав int.
@Delete
int delete(List<Employee> employee);
Анотації Insert, Update і Delete дають змогу виконати прості операції. Для складніших дій необхідно використовувати SQL запити: INSERT, UPDATE і DELETE. Це можна зробити за допомогою анотації Query.
Транзакції
Анотація @Transaction дає змогу виконувати кілька методів у межах однієї транзакції.
Розглянемо приклад, коли нам потрібно додати об'єкти Car і Employee:
@Dao
public abstract class EmployeeCarDao {
@Insert
public abstract void insertEmployee(Employee employee);
@Insert
public abstract void insertCar(Car car);
@Transaction
public void insertCarAndEmployee(Car car, Employee employee) {
insertCar(car);
insertEmployee(employee);
}
}
EmployeeCarDao - окремий Dao об'єкт для роботи з комбінацією Car і Employee. У ньому описуємо методи для вставки об'єктів окремо, а потім обидва ці методи викликаємо в одному методі з анотацією Transaction. У підсумку вставляться або обидва об'єкти, або, у разі виникнення помилки, жоден із них.
Зверніть увагу, що в цьому випадку Dao - не інтерфейс, а абстрактний клас.