Android 구성 요소 룸 안내

프로필
Room 은 Google 이 출시 한 Android 구성 요소 라 이브 러 리 의 데이터 영구 화 구성 요소 라 이브 러 리 이 며 SQLite 에서 이 루어 진 ORM 솔 루 션 이 라 고 할 수 있 습 니 다.
Room 은 주로 세 부분 을 포함 합 니 다.
  • Database:DB 와 DAO
  • 보유
  • Entity:POJO 류,즉 데이터 시트 구조
  • 를 정의 합 니 다.
  • DAO(Data Access Objects):액세스 데이터(추가 삭제 및 검사)를 정의 하 는 인터페이스
  • 그 관 계 는 다음 그림 과 같다.

    Room Architecture Diagram
    기본 사용
    1.엔 터 티 만 들 기
    1.1 간단 한 Entitiy
    간단 한 Entity 정 의 는 다음 과 같 습 니 다.
    
    @Entity(tableName = "user" 
      indices = {@Index(value = {"first_name", "last_name"})})
    public class User {
     @PrimaryKey
     private int uid;
     @ColumnInfo(name = "first_name")
     private String firstName;
     @ColumnInfo(name = "last_name")
     private String lastName;
     @Ignore
     public User(String firstName, String lastName) {
     this.uid = UUID.randomUUID().toString();
     this.firstName = firstName;
     this. lastName = lastName;
     }
     public User(String id, String firstName, String lastName) {
     this.uid = id;
     this.firstName = userName;
     this. lastName = userName;
     }
     // Getters and setters
    }
  • @Entity(tableName = "table_name**")POJO 클래스 를 주석 하고 데이터 시트 이름 을 정의 합 니 다.
  • @Primary Key 는 메 인 키 를 정의 합 니 다.하나의 Entity 가 복합 메 인 키 를 사용한다 면@Entity 가 설명 한 primaryKeys 속성 을 통 해 복합 메 인 키 를 정의 할 수 있 습 니 다.@Entity(primaryKeys={"firstName","lastName"}
  • @ColumnInfo(name = “column_")데이터 시트 의 필드 이름 을 정의 합 니 다
  • @Ignore 는 Room 에 무시 해 야 할 필드 나 방법 을 알려 주 는 데 사 용 됩 니 다
  • 색인 만 들 기:@Entity 주해 의 indices 속성 에 색인 필드 를 추가 합 니 다.예 를 들 어 indices={@Index(value={"firstname", "last_name"},unique=true),...},unique=true 는 표 에{"first 가 나타 나 지 않도록 할 수 있 습 니 다.name", "last_name"}같은 데이터 입 니 다.
  • 1.2 Entitiy 간 의 관계
    현재 존재 하 는 대부분의 ORM 라 이브 러 리 와 달리 Room 은 Entitiy 대상 간 의 직접 인용 을 지원 하지 않 습 니 다.
    다만 Room 은 엔 터 티 간 관 계 를 외부 키(Foreign Key)로 표시 할 수 있다.
    
    @Entity(foreignKeys = @ForeignKey(entity = User.class,
         parentColumns = "id",
         childColumns = "user_id"))
    class Book {
     @PrimaryKey
     public int bookId;
     public String title;
     @ColumnInfo(name = "user_id")
     public int userId;
    }
    위의 코드 에서 보 듯 이 Book 대상 과 User 대상 은 속 하 는 관계 입 니 다.북 속 userid,사용자 의 id 에 대응 합 니 다.그렇다면 사용자 대상 이 삭 제 될 때 해당 하 는 북 은 어떻게 될 까?
    @ForeignKey 주석 에는 두 개의 속성 이 있 습 니 다.onDelete 와 onUpdate.이 두 속성 은 ForeignKey 의 onDelete()와 onUpdate()에 대응 합 니 다.이 두 속성의 값 을 통 해 User 대상 이 삭제/업데이트 되 었 을 때 Book 대상 이 하 는 응답 을 설정 합 니 다.이 두 속성의 선택 값 은 다음 과 같 습 니 다.
  • CASCADE:사용자 가 삭 제 했 을 때 해당 하 는 Book 과 함께 삭 제 됩 니 다.업데이트 시 관련 필드 함께 업데이트
  • NO_ACTION:사용자 삭제 시 응답 하지 않 음
  • RESTRICT:사용자 의 삭제/업 데 이 트 를 금지 합 니 다.사용자 가 삭제 하거나 업데이트 할 때 Sqlite 는 즉시 오 류 를 보고 합 니 다.
  • SET_NULL:사용자 가 삭제 하면 북 의 userId 는 NULL
  • 로 설 정 됩 니 다.
  • SET_DEFAULT:SETNULL 과 유사 합 니 다.사용자 가 삭제 할 때 Book 의 userId 는 기본 값
  • 으로 설 정 됩 니 다.
    1.3 개체 내장
    어떤 경우 에는 표 의 데이터 에 대해 여러 개의 POJO 클래스 로 표시 합 니 다.이 경우@Embedded 로 포 함 된 대상 을 설명 할 수 있 습 니 다.예 를 들 어:
    
    class Address {
     public String street;
     public String state;
     public String city;
     @ColumnInfo(name = "post_code")
     public int postCode;
    }
    @Entity
    class User {
     @PrimaryKey
     public int id;
     public String firstName;
     @Embedded
     public Address address;
    }
    위 코드 에서 생 성 된 User 표 에서 Column 은 id,firstName,street,state,city,post 입 니 다.code
    2.데이터 접근 대상 만 들 기(DAO)
    
    @Dao
    public interface UserDao {
     @Query("SELECT * FROM user")
     List<User> getAll();
     @Query("SELECT * FROM user WHERE uid IN (:userIds)")
     List<User> 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(List<User> users);
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     public void insertUsers(User... users);
     @Delete
     void delete(User user);
     @Update
     public void updateUsers(List<User> users);
    }
    DAO 는 하나의 인터페이스 일 수도 있 고 추상 적 인 클래스 일 수도 있 습 니 다.Room 은 컴 파일 할 때 DAO 의 실현 을 만 듭 니 다.
    Tips:
  • @Insert 방법 도 반환 값 을 정의 할 수 있 습 니 다.들 어 오 는 매개 변수 가 하나 일 때 log 로 돌아 가 고 여러 개 들 어 올 때 log[]또는 List으로 돌아 갑 니 다.Room 은 insert 방법 이 실 현 될 때 하나의 사무 에 모든 매개 변 수 를 삽입 합 니 다.
  • @Insert 의 매개 변수 가 충돌 할 때 onConflict 속성의 값 을 설정 하여 충돌 해결 전략 을 정의 할 수 있 습 니 다.예 를 들 어 코드 에서 정 의 된 것 은@Insert(onConflict=OnConflict Strategy.REPLACE)입 니 다.즉,충돌 이 발생 할 때 기 존 데 이 터 를 교체 하 는 것 입 니 다
  • .
  • @Update 와@Delete 는 int 형식 반환 값 을 정의 할 수 있 습 니 다.업데이트/삭제 함수
  • 를 말 합 니 다.
    DAO 의 첨삭 방법 에 대한 정 의 는 모두 비교적 간단 하 다.여 기 는 토론 을 하지 않 고 다음 에 조회 방법 에 대해 더 이야기 하 겠 다.
    2.1 간단 한 조회
    Talk is cheap,직접 표시 코드:
    
    @Query("SELECT * FROM user")
    List<User> getAll();
    Room 은 컴 파일 할 때 sql 문 구 를 검사 합 니 다.@Query()의 sql 문 구 는 문법 오류 가 있 거나 조회 표 가 존재 하지 않 으 면 Room 은 컴 파일 타 임 스 가 잘못 되 었 습 니 다.
    2.2 조회 매개 변수 전달
    
    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> 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);
    코드 를 보면 이해 하기 쉬 울 것 입 니 다.방법 에서 매개 변수 arg 를 전달 하고 sql 구문 에서:arg 를 사용 하면 됩 니 다.컴 파일 할 때 Room 은 대응 하 는 인자 와 일치 합 니 다.
    전송 인삼 에 arg 에 대응 하 는 인자 가 일치 하지 않 으 면 Room 은 컴 파일 타 임 스 가 잘못 되 었 습 니 다.
    2.3 조회 표 의 일부 필드 의 정보
    실제 특정한 업무 장면 에서 우 리 는 표 부분 필드 의 값 에 만 관심 을 가 질 수 있 습 니 다.이때 저 는 관심 있 는 열 만 조회 하면 됩 니 다.
    부분 집합 을 정의 하 는 POJO 클래스:
    
    public class NameTuple {
     @ColumnInfo(name="first_name")
     public String firstName;
    
     @ColumnInfo(name="last_name")
     public String lastName;
    }
    DAO 에 검색 방법 추가:
    
    @Query("SELECT first_name, last_name FROM user")
    public List<NameTuple> loadFullName();
    여기 서 정 의 된 POJO 도@Embedded 사용 을 지원 합 니 다.
    2.3 검색 결과 의 반환 유형
    Room 에서 조회 작업 은 POJO 대상 과 List 를 되 돌려 주 는 것 외 에 도 지원 합 니 다.
    LiveData:
    LiveData 는 구성 요소 라 이브 러 리 에서 제공 하 는 또 다른 구성 요소 로 데이터 변화 구동 UI 새로 고침 수 요 를 잘 만족 시 킬 수 있 습 니 다.Room 은 LiveData 코드 를 업데이트 합 니 다.
    
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)") 
    public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
    Flowablbe<T> Maybe<T> Single<T>:
    Room     RxJava2  Flowablbe, Maybe Single  ,    RxJava          ,     gradle     :android.arch.persistence.room:rxjava2。
    @Query("SELECT * from user where id = :id LIMIT 1")
    public Flowable<User> loadUserById(int id);
    
    
    Cursor:
    Cursor 로 돌아 가 는 것 은 기 존 프로젝트 에서 Cursor 를 사용 하 는 장면 을 지원 하기 위해 서 입 니 다.공식 적 으로 는 Cursor 로 돌아 가 는 것 을 권장 하지 않 습 니 다.
    Caution: It's highly discouraged to work with the Cursor API because it doesn't guarantee whether the rows exist or what values the rows contain. Use this functionality only if you already have code that expects a cursor and that you can't refactor easily.
    2.4 연표 조회
    Room 은 연결 표 조 회 를 지원 합 니 다.인터페이스 정의 에 있어 서 다른 조회 와 차이 가 크 지 않 습 니 다.주로 sql 문장의 차이 입 니 다.
    
    @Dao
    public interface MyDao {
     @Query("SELECT * FROM book "
      + "INNER JOIN loan ON loan.book_id = book.id "
      + "INNER JOIN user ON user.id = loan.user_id "
      + "WHERE user.name LIKE :userName")
     public List<Book> findBooksBorrowedByNameSync(String userName);
    }
    3.데이터베이스 만 들 기
    Room 에서 DataBase 는 SQLite API 에서 SQLiteOpenHelper 와 유사 하여 DB 작업 을 제공 하 는 착안점 이지 만 DB 를 가지 고 있 는 것 외 에 관련 데이터 시트(Entity)를 가 진 데이터 액세스 대상(DAO)도 책임 지기 때문에 Room 에서 Database 를 정의 하려 면 세 가지 조건 을 만족 시 켜 야 합 니 다.
  • RoomDataBase 를 계승 하고 추상 류
  • @Database 로 주석 을 달 고 관련 entity 대상 을 정의 합 니 다.물론 빠 질 수 없 는 데이터베이스 버 전 정보
  • 도 있 습 니 다.
  • DAO 대상 을 되 돌려 주 는 추상 적 인 방법 정의
  • 
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
     public abstract UserDao userDao();
    }
    이상 Room 의 3 대 구성 요 소 를 만 든 후 코드 에서 다음 코드 를 통 해 Database 인 스 턴 스 를 만 들 수 있 습 니 다.
    
    AppDatabase db = Room.databaseBuilder(getApplicationContext(),
     AppDatabase.class, "database-name").build();
    3.데이터베이스 이전
    3.1 룸 데이터베이스 업그레이드
    전통 적 인 SQLite API 에서 데이터 베 이 스 를 업그레이드 하려 면 SQLiteOpenHelper.onUpgrade 방법 으로 데이터 베 이 스 를 업그레이드 하 는 sql 문 구 를 실행 합 니 다.이러한 sql 문 구 는 보통 데이터 베이스 버 전에 따라 파일 방식 이나 배열 로 관리 합 니 다.이런 방식 으로 데이터 베 이 스 를 업그레이드 하 는 것 은 폭탄 을 뜯 는 것 과 같다 는 말 이 있다.그 에 비해 Room 에서 데이터 베 이 스 를 업그레이드 하 는 것 은 하나의 스위치 를 누 르 는 것 과 같다.
    Room 은 데이터 베 이 스 를 업그레이드 하기 위해 Migration 류 를 제공 합 니 다.
    
    Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
     .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
     @Override
     public void migrate(SupportSQLiteDatabase database) {
     database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
      + "`name` TEXT, PRIMARY KEY(`id`))");
     }
    };
    static final Migration MIGRATION_2_3 = new Migration(2, 3) {
     @Override
     public void migrate(SupportSQLiteDatabase database) {
     database.execSQL("ALTER TABLE Book "
      + " ADD COLUMN pub_year INTEGER");
     }
    };
    Migration 클래스 를 만 들 때 startVersion 과 endVersion 을 지정 해 야 합 니 다.코드 에 MIGRATION1_2 와 MIGRATION2_3 의 startVersion 과 endVersion 은 점차 증가 합 니 다.Migration 은 버 전 1 에서 버 전 3 으로 바로 올 라 가 는 것 을 지원 합 니 다.migrate()방법 에서 실 행 된 문구 가 정상 적 이면 됩 니 다.그러면 Room 은 어떻게 데이터베이스 업 그 레이 드 를 실현 합 니까?사실은 본질 적 으로 SQLiteOpenHelper.onUpgrade 를 호출 합 니 다.Room 에서 자체 적 으로 SQLiteOpenHelper 를 실 현 했 습 니 다.onUpgrade()방법 이 호출 될 때 Migration 을 촉발 합 니 다.데이터 베 이 스 를 처음 방 문 했 을 때 Room 은 다음 과 같은 몇 가지 일 을 했 습 니 다.
  • Room Database 인 스 턴 스 생 성
  • SQLiteOpenHelper.onUpgrade 가 호출 되 고 Migration
  • 이 실 행 됩 니 다.
  • 데이터베이스 열기
  • 그 러 고 보 니 룸 에서 데이터베이스 업 그 레이 드 를 처리 하 는 것 은 스위치 를 추가 하 는 것 과 비슷 하 다.
    3.2 기 존 SQLite 데이터 베 이 스 를 Room 으로 이전
    Room 도 SQLite 를 사용 하기 때문에 기 존 Sqlite 데이터 베 이 스 를 Room 으로 이전 하 는 것 을 잘 지원 할 수 있 습 니 다.
    기 존 버 전 번호 가 1 인 데이터베이스 에 표 User 가 있다 고 가정 하고 Room 으로 이전 하려 면 Entity,DAO,Database 를 정의 한 다음 Database 를 만 들 때 빈 Migration 을 추가 하면 됩 니 다.주의해 야 할 것 은 데이터베이스 에 업그레이드 작업 이 없 더 라 도 버 전 을 업그레이드 해 야 합 니 다.그렇지 않 으 면 IllegalState Exception 을 버 릴 수 있 습 니 다.
    
    @Database(entities = {User.class}, version = 2)
    public abstract class UsersDatabase extends RoomDatabase {
    …
    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
     @Override
     public void migrate(SupportSQLiteDatabase database) {
     // Since we didn't alter the table, there's nothing else to do here.
     }
    };
    …
    database = Room.databaseBuilder(context.getApplicationContext(),
     UsersDatabase.class, "Sample.db")
     .addMigrations(MIGRATION_1_2)
     .build();
    4.복잡 한 데이터 의 처리
    일부 장면 에서 우리 의 응용 은 Date 와 같은 복잡 한 데이터 형식 을 저장 해 야 할 수도 있 습 니 다.그러나 Room 의 Entity 는 기본 데이터 형식 과 포장 류 간 의 전환 만 지원 하고 다른 대상 의 인용 은 지원 하지 않 습 니 다.그래서 Room 은 TypeConverter 를 제공 하여 사용자 자신 에 게 대응 하 는 전환 을 실현 합 니 다.
    Date 형식의 변환 은 다음 과 같 습 니 다.
    
    public class Converters {
     @TypeConverter
     public static Date fromTimestamp(Long value) {
     return value == null ? null : new Date(value);
     }
     @TypeConverter
     public static Long dateToTimestamp(Date date) {
     return date == null ? null : date.getTime();
     }
    }
    변환 방법 을 정의 한 후 대응 하 는 Database 에 지정 하면 됩 니 다.그러면 대응 하 는 POJO(User)에서 Date 클래스 를 사용 할 수 있 습 니 다.
    
    @Database(entities = {User.class}, version = 1)
    @TypeConverters({Converters.class})
    public abstract class AppDatabase extends RoomDatabase {
     public abstract UserDao userDao();
    }
    @Entity
    public class User {
     ...
     private Date birthday;
    }
    총화
    SQLite API 방식 으로 데이터 영구 화 를 실현 하 는 프로젝트 에서 하나의 작업 이 힘 든 SQLite OpenHelper 가 실 현 될 것 이 라 고 믿 습 니 다.유지 보수 표 의 필드 에 있 는 Constant 류,코드 가 유사 한 데이터베이스 액세스 류(DAO)가 있 습 니 다.데이터 베 이 스 를 방문 할 때 Cursor 를 옮 겨 다 니 며 해당 하 는 POJO 류 를 구축 하고 되 돌려 야 합 니 다.비교 해 보면,Room 은 SQLite 위 에 포 장 된 ORM 라 이브 러 리 로 서 많은 장점 을 가진다.비교적 직관 적 인 체험 은 다음 과 같다.
  • SQLite API 보다 간단 한 사용 방식
  • 중복 코드 를 많이 생략 했다
  • 컴 파일 할 때 sql 문장의 정확성 을 검증 할 수 있 습 니 다
  • 데이터베이스 와 관련 된 코드 는 Entity,DAO,Database 세 부분 으로 나 뉘 는데 구조 가 뚜렷 하 다
  • 간단 하고 안전 한 데이터베이스 업그레이드 방안

  • 총결산
    위 에서 말 한 것 은 소 편 이 소개 한 안 드 로 이 드 구조 구성 요소 Room 안내 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 메 시 지 를 남 겨 주세요.소 편 은 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기