Room android studio java

Save data in a local database using Room Part of Android Jetpack.

Apps that handle non-trivial amounts of structured data can benefit greatly from persisting that data locally. The most common use case is to cache relevant pieces of data so that when the device cannot access the network, the user can still browse that content while they are offline.

The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. In particular, Room provides the following benefits:

  • Compile-time verification of SQL queries.
  • Convenience annotations that minimize repetitive and error-prone boilerplate code.
  • Streamlined database migration paths.

Because of these considerations, we highly recommend that you use Room instead of using the SQLite APIs directly.

Setup

To use Room in your app, add the following dependencies to your app’s build.gradle file:

Groovy

Kotlin

Primary components

There are three major components in Room:

  • The database class that holds the database and serves as the main access point for the underlying connection to your app’s persisted data.
  • Data entities that represent tables in your app’s database.
  • Data access objects (DAOs) that provide methods that your app can use to query, update, insert, and delete data in the database.
Читайте также:  Меньше либо равно html

The database class provides your app with instances of the DAOs associated with that database. In turn, the app can use the DAOs to retrieve data from the database as instances of the associated data entity objects. The app can also use the defined data entities to update rows from the corresponding tables, or to create new rows for insertion. Figure 1 illustrates the relationship between the different components of Room.

Sample implementation

This section presents an example implementation of a Room database with a single data entity and a single DAO.

Data entity

The following code defines a User data entity. Each instance of User represents a row in a user table in the app’s database.

Kotlin

@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )

Java

To learn more about data entities in Room, see Defining data using Room entities.

Data access object (DAO)

The following code defines a DAO called UserDao . UserDao provides the methods that the rest of the app uses to interact with data in the user table.

Kotlin

@Dao interface UserDao < @Query("SELECT * FROM user") fun getAll(): List@Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) >

Java

@Dao public interface UserDao < @Query("SELECT * FROM user") ListgetAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User. users); @Delete void delete(User user); >

Database

The following code defines an AppDatabase class to hold the database. AppDatabase defines the database configuration and serves as the app’s main access point to the persisted data. The database class must satisfy the following conditions:

  • The class must be annotated with a @Database annotation that includes an entities array that lists all of the data entities associated with the database.
  • The class must be an abstract class that extends RoomDatabase .
  • For each DAO class that is associated with the database, the database class must define an abstract method that has zero arguments and returns an instance of the DAO class.

Kotlin

@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase()

Java

@Database(entities = , version = 1) public abstract class AppDatabase extends RoomDatabase

Note: If your app runs in a single process, you should follow the singleton design pattern when instantiating an AppDatabase object. Each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances within a single process.

If your app runs in multiple processes, include enableMultiInstanceInvalidation() in your database builder invocation. That way, when you have an instance of AppDatabase in each process, you can invalidate the shared database file in one process, and this invalidation automatically propagates to the instances of AppDatabase within other processes.

Usage

After you have defined the data entity, the DAO, and the database object, you can use the following code to create an instance of the database:

Kotlin

val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()

Java

AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();

You can then use the abstract methods from the AppDatabase to get an instance of the DAO. In turn, you can use the methods from the DAO instance to interact with the database:

Kotlin

val userDao = db.userDao() val users: List = userDao.getAll()

Java

UserDao userDao = db.userDao(); List users = userDao.getAll();

Additional resources

To learn more about Room, see the following additional resources:

Samples

Codelabs

Blogs

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2023-06-26 UTC.

Источник

Room: Хранение данных на Android для всех и каждого

Room — это новый способ сохранить данные приложений в Android-приложении, представленный в этом году на Google I/O. Это часть новойAndroid Architecture, группа библиотек от Google, которые поддерживают уместную архитектуру приложений. Room предлагается в качестве альтернативы Realm, ORMLite, GreenDao и многим другим.

Room — это высокоуровневый интерфейс для низкоуровневых привязок SQLite, встроенных в Android, о которых вы можете узнать больше в документации. Он выполняет большую часть своей работы во время компиляции, создавая API-интерфейс поверх встроенного SQLite API, поэтому вам не нужно работать с Cursor или ContentResolver.

Использование Room

Во-первых, добавьте Room в свой проект. После этого вам нужно будет передать в Room, как выглядят ваши данные. Предположим, имеется простой класс модели, который выглядит следующим образом:

Чтобы рассказать Room о классе Person, добавляем аннотицию Entity к классу и @PrimaryKey к ключу:

@Entity public class Person

Благодаря этим двум аннотациям Room теперь знает, как создать таблицу для хранения экземпляров Person.

Важная вещь, которую следует учитывать при настройке ваших моделей: каждое поле, которое хранится в базе данных, должно быть общедоступным или иметь геттер и сеттер в стандартном стиле Java Beans (например, getName () и setName (имя строки)).

В классе Person теперь есть вся информация, которая требуется Room для создания таблиц, но у вас нет способа фактически добавлять, запрашивать или удалять данные из базы данных. Вот почему вам нужно будет сделать объект доступа к данным (DAO). DAO предоставляет интерфейс в самой базе данных и занимается манипулированием хранимыми данными Person.

Вот простой интерфейс DAO для класса Person:

@Dao public interface PersonDao < // Добавление Person в бд @Insert void insertAll(Person. people); // Удаление Person из бд @Delete void delete(Person person); // Получение всех Person из бд @Query("SELECT * FROM person") ListgetAllPeople(); // Получение всех Person из бд с условием @Query("SELECT * FROM person WHERE favoriteColor LIKE :color") List getAllPeopleWithFavoriteColor(String color); >

Первое, что нужно заметить, это то, что PersonDaoэто интерфейс, а не класс. Другая интересная деталь — это инструкции SQL в аннотациях Query (). Операторы SQL говорят Room, какую информацию вы хотите получить из базы данных. Они также проверяются во время компиляции. Поэтому, если вы измените подпись метода List getAllPeopleWithFavoriteColor ( название цвета ) на List getAllPeopleWithFavoriteColor ( int color ), Room выдаст ошибку во время компиляции:

incompatible types: int cannot be converted to String

И если вы сделаете опечатку в выражении SQL, например, напишите favoriteColors ( множественное число ) вместо favoriteColor ( единственное число ), Room также выдаст ошибку компиляции:

There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: favoriteColors)

Вы не можете получить экземпляр PersonDao, потому что это интерфейс. Чтобы иметь возможность использовать классы DAO, вам необходимо создать класс базы данных. За кулисами этот класс будет отвечать за ведение самой базы данных и предоставление экземпляров DAO.

Вы можете создать свой класс базы данных всего за пару строк:

@Database(entities = , version = 1) public abstract class AppDatabase extends RoomDatabase

Это лишь описание структуры базы данных, но сама база данных будет жить в одном файле. Чтобы получить экземпляр AppDatabase, сохраненный в файле с именем populus-database, вы должны написать:

AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "populus-database").build();

Если вы хотите получить все данные обо всех Person, которые находятся в базе данных, вы могли бы написать:

List everyone = db.getPersonDao().getAllPeople();

Преимущества использования Room

В отличие от большинства ORM, Room использует обработчик аннотации для выполнения всей своей манеры сохранения данных. Это означает, что ни ваши классы приложений, ни классы моделей не должны ничего расширять в Room, в отличие от многих других ORM, включая Realm и SugarORM. Как вы видели при ошибках с аннотациями Query () выше, вы также получаете возможность проверки корректности SQL-запросов во время компиляции, что может сэкономить вам много хлопот.

Room также позволяет вам наблюдать за изменениями данных, интегрируя их как с API LiveData Архитектурных Компонентов, так и с RxJava 2. Это означает, что если у вас сложная схема, где изменения в базе данных должны появляться в нескольких местах вашего приложения, Room делает уведомления об изменениях. Это мощное дополнение может быть включено одной строкой. Все, что вам нужно сделать, это изменить тип возвращаемых значений.

@Query("SELECT * FROM person") List getAllPeople();
@Query("SELECT * FROM person") LiveData> /* or Observable> */ getAllPeople();

Самое большое ограничение в Room: взаимосвязи

Самым большим ограничением в Room является то, что он не будет обрабатывать отношения с другими типами сущностей для вас автоматически, как и другие ORM. Это означает, что если вы хотите отслеживать домашних животных:

@Entity public class Person < @PrimaryKey String name; int age; String favoriteColor; Listpets; > @Entity public class Pet

То Room выдаст ошибку компиляци, так как не знает, как сохранить отношения между Person и Pet:

Cannot figure out how to save this field into database. You can consider adding a type converter for it.

Ошибка при компиляции предлагает конвертер типов, который преобразует объекты в примитивы, которые могут быть непосредственно сохранены в SQL. Поскольку List нельзя свести к примитиву, вам нужно сделать что-то другое. Это отношения «один ко многим», где у одного Person может быть много Pet. Room не может моделировать такие отношения, но она может справиться с обратными отношениями — у каждого Pet есть один Person. Чтобы смоделировать это, удалите поле для Pet в Person и добавьте поле ownerId в класс Pet:

@Entity public class Person < @PrimaryKey String name; int age; String favoriteColor; >@Entity(foreignKeys = @ForeignKey( entity = Person.class, parentColumns = "name", childColumns = "ownerId")) public class Pet < @PrimaryKey String name; String breed; String ownerId; // this ID points to a Person >

Это приведет к тому, что Room обеспечит ограничение внешнего ключа между объектами. Room не будет вызывать отношения «один-ко-многим» и «много-к-одному», но она дает вам инструменты для выражения этих отношений.

Чтобы получить всех домашних животных, принадлежащих конкретному человеку, вы можете использовать запрос, который находит всех домашних животных с данным идентификатором владельца. Например, вы можете добавить в свой DAO следующий метод:

@Query("SELECT * FROM pet WHERE ownderId IS :ownerId") List getPetsForOwner(String ownerId);

Стоит ли использовать Room?

Если вы уже настроили сохранение данных в своем приложении и довольны им, то ничего не изменяйте. Каждая ORM и встроенная реализация SQLite будут продолжать работать так же, как и раньше. Room — это всего лишь еще один вариант сохранения данных.

Если вы используете SQLite или собираетесь использовать его, вы должны попробовать Room. Он обладает всеми возможностями, необходимыми для выполнения расширенных запросов, одновременно устраняя необходимость писать SQL-запросы для поддержки базы данных самостоятельно.

Источник

Оцените статью