Posts Android Database - Realm
Post
Cancel

Android Database - Realm

Android Realm Database

Realm(렘)은 오픈소스 데이터베이스 관리시스템(DBMS) 이며 모바일 환경을 주요 타깃으로 삼은 데이터베이스이다.
Realm은 매우 작은 리소스를 사용하고 사용하기 쉽고 더 빠르게 데이터와 상호 작용 가능하다.
NoSQL 데이터베이스를 지향하며 rawSQL을 사용할 수 없어 Realm API를 통해서 실행된다.

한국어 공식 문서도 제공하지만 kotlin 인 경우 현제 영어 문서만 제공하고 있다.
Java : https://realm.io/docs/java/latest/
Kotlin : https://realm.io/docs/kotlin/latest/

SQL Queries Realm Queries

시작하기

프로젝트 레벨의 gradle 파일에 아래와 같이 class path를 추가해준다.

1
2
3
4
5
6
7
8
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:7.0.0-beta"
    }
}

애플리케이션 레벨의 gradle 파일에 플러그인을 추가해준다.

1
2
3
4
5
apply plugin: 'com.android.application'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'

Kotlin 으로 사용시 주의 사항

  1. 모델 클래스는 open 으로 선언되어야 한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    enum class MyEnum {
     Value1, Value2
    }
    open class EnumTest: RealmObject() {
     // Custom private backing field representing the enum
     private var strField: String = MyEnum.Value1.name
    
     // Public field exposing setting/getting the enum
     var enumField: MyEnum
         get() = MyEnum.values().first { it.name == strField }
         set(value) {
             strField = value.name
         }
    }
    // Queries
    val results = realm.where<EnumTest>().equalTo("strField", MyEnum.Value1.name).findAll()
    
  2. primitive type wrapper class 구분
    1
    2
    3
    4
    
    schema
      .addField("field", Long::class.java) // Non-nullable (long)
      .addField("field", Long::class.javaObjectType) // Nullable (Long)
      .addField("field", Long::class.javaPrimitiveType) // Non-nullable (long)
    

Realm 초기화

Application 클래스에서 Realm 을 초기화 해준다.

1
2
3
4
5
6
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Realm.init(this)
    }
}

AndroidManifest.xml에 Application class를 등록해준다.

1
2
3
4
<application
  android:name=".MyApplication"
  ...
/>

Realm 설정하기

Realm 을 설정하기 위해 RealmCongiguration 객체를 사용한다. default로 설정하기 위해서는 아래와 같이 사용된다.

1
val config = RealmConfiguration.Builder().build()

이와 같이 사용하는 경우 Context.getFilesDir에 위치에 default.realm 파일을 저장한다.

전형적으로 사용하는 방법은 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
// The RealmConfiguration is created using the builder pattern.
// The Realm file will be located in Context.getFilesDir()
// with name "myrealm.realm"
val config = RealmConfiguration.Builder()
    .name("myrealm.realm")
    .encryptionKey(getMyKey())
    .schemaVersion(42)
    .modules(MySchemaModule())
    .migration(MyMigration())
    .build()
// Use the config
val realm = Realm.getInstance(config)

RealmConfiguration을 Default로 설정하기

Custom Application class에서 RealmConfiguration 클래스에 있는 setDefaultConfiguration 매서드를 사용해서 default를 설정할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // The default Realm file is "default.realm" in Context.getFilesDir();
        // we'll change it to "myrealm.realm"
        Realm.init(this)
        val config = RealmConfiguration.Builder().name("myrealm.realm").build()
        Realm.setDefaultConfiguration(config)
    }
}

class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val realm = Realm.getDefaultInstance() // opens "myrealm.realm"
        try {
            // ... Do something ...
        } finally {
            realm.close()
        }
    }
}

Realm 모델 생성하기

RealmObject class 를 상속받아 구현한다. (open 으로 정의하기!!)

1
2
3
4
5
6
7
open class User(
    var name: String = "",
    var age: Int = 0,

    @Ignore
    var sessionId: Int = 0
): RealmObject()

Required fields

  • 필드에서 null을 허용하지 않을꺼면 @Require를 필드에 추가해준다.

속성 인덱싱

  • @Index annotation을 추가해주면 그 필드를 기준으로 인덱싱된다. 인덱싱을 하면, 데이터 추가가느려지며 파일이 커지는 단점이 있다. 대신 query가 빨라진다.
  • String, Byte, Shore, Int, Long, Boolean, Date 필드에서만 사용 가능하다.

Primary Key

  • @PrimaryKey annotation 을 사용해서 기본키를 설정한다.
  • @PrimaryKey@Index annotation을 포함하고 있다.
  • Primary key를 사용하면 copyToRealmOrUpdate 메서드를 사용할 수 있는데 업데이트 시, 키를 이용해서 객체를 찾으면 그 객체를 업데이트를 하고 못찾으면 새로운 객체를 생성한다. (@PrimaryKey 가 선언되어 있지 않으면 exception 발생)
  • Realm.createObject 는 모든 필드에 기본값이 채워져서 객체를 생성하는데 기본키가 중복이 될 수도 있다.
    • 이를 해결하기 위해서 copyToRealm 메서드를 사용하는데 똑같은 키를 가지면 exception이 발생한다.
1
2
3
4
5
6
7
8
9
10
11
12
val obj = MyObject()
obj.id = 42
obj.name = "Fish"
realm.executeTransaction { realm ->
    // This will create a new object in Realm or throw an exception if the
    // object already exists (same primary key)
    // realm.copyToRealm(obj);

    // This will update an existing object with the same primary key
    // or create a new object if an object with no primary key = 42
    realm.copyToRealmOrUpdate(obj)
}

@Ignore

  • Realm 필드를 저장하고 싶지 않을 때 사용한다.
  • static, trasient은 항상 @Ingnore로 설정된다.
This post is licensed under CC BY 4.0 by the author.