Docs Menu
Docs Home
/ /
Atlas Device SDK
/ / /

Realm 객체 업데이트 - Kotlin SDK

이 페이지의 내용

  • 업데이트 작업
  • 기존 객체 업데이트
  • Realm 객체 업데이트
  • 내장된 객체 업데이트
  • 다중 객체 업데이트
  • Realms 속성 업데이트
  • MutableRealmInt(카운터) 속성 업데이트
  • RealmAny(혼합) 속성 업데이트
  • 컬렉션 속성 업데이트
  • RealmList 업데이트
  • RealmSet 업데이트
  • 사전 업데이트
  • 관계 업데이트
  • To-One 관계 업데이트
  • To-Many 관계 업데이트
  • 역관계 업데이트
  • Realm 객체 업서트

이 페이지에서는 Kotlin SDK를 사용하여 로컬 또는 동기화된 영역에서 기존 Realm 객체를 업데이트하는 방법에 대해 설명합니다. 영역에서 객체를 만드는 방법에 대해 자세히 알아보려면 Realm 객체 만들기 - Kotlin SDK를 참조하세요.

Realm 은 Realm 객체 및 포함된 객체에 대한 업데이트 및 업서트 작업을 지원합니다. 업서트 작업 은 객체 의 새 인스턴스 를 삽입하거나 특정 기준을 충족하는 기존 객체 를 업데이트합니다. 자세한 내용은 이 페이지의 Realm 객체 업서트 섹션을 참조하세요.

비대칭 객체는 업데이트 할 수 없습니다 . 이는 비대칭 객체가 영역에서 유지되지 않는 특수한 쓰기 전용 객체이기 때문입니다. 애플리케이션에서 비대칭 객체를 사용하는 방법에 대한 자세한 내용은 Atlas로 데이터 스트리밍 - Kotlin SDK를 참조하세요.

참고

동기화된 Realm에 쓰기

영역에서 객체를 업데이트하는 구문은 로컬 또는 동기화된 영역에서 동일합니다. 그러나 동기화된 영역 내 쓰기 작업의 성공 여부를 결정하는 데에는 추가적인 고려 사항이 있습니다. 자세한 내용은 동기화된 Realm에 데이터 쓰기 - Kotlin SDK를 참조하세요.

업데이트 및 업서트 작업을 포함하여 영역 을 수정하는 모든 작업은 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction)) 내에서 수행되어야 합니다. 쓰기 트랜잭션(write transaction)은 영역의 쓰기 (write)() 또는 writeBlocking() 메서드로 전달됩니다. 이 콜백 내에서 MutableRealm 인스턴스 에 액세스 한 다음 영역 내의 객체를 업데이트 할 수 있습니다. 쓰기 트랜잭션(write transaction)과 Realm 에서 쓰기 트랜잭션(write transaction)을 처리하는 방법에 대한 자세한 내용은 쓰기 (write) 트랜잭션(write transaction)을 참조하세요 .

또한 쓰기 트랜잭션(write transaction) 내부에서만 액세스할 수 있는 라이브 객체만 수정할 수 있습니다. mutableRealm.findLatest()를 사용하여 트랜잭션에서 동결된 객체를 라이브 객체로 변환할 수 있습니다.

예시

수정하기 전에 고정된 객체 변환

val frozenFrog = realm.query<Frog>().find().first()
// Open a write transaction
realm.write {
// Get the live frog object with findLatest(), then update it
findLatest(frozenFrog)?.let { liveFrog ->
liveFrog.name = "Kermit"
liveFrog.age -= 1
}
}

Realm 객체 또는 영역 내에 저장된 내장된 객체의 속성을 수정하려면 다음을 수행하세요.

  1. realm.write() 로 쓰기 트랜잭션(write transaction)을 엽니다. 또는 realm.writeBlocking().

  2. 쿼리 ()를 사용하여 수정하려는 객체에 대해 트랜잭션의 변경 가능한 영역 을 쿼리하여 라이브 객체 를 가져옵니다.

    1. query()에 전달된 유형 매개변수로 객체 유형을 지정합니다.

    2. (선택 사항) 쿼리를 지정하여 반환된 객체 세트를 필터링합니다. 쿼리 필터를 포함하지 않으면 지정된 유형의 모든 객체가 반환됩니다. Kotlin SDK를 사용한 쿼리에 대한 자세한 내용은 Realm 객체 읽기 - Kotlin SDK를 참조하세요.

    중요

    객체가 라이브 상태여야 함

    라이브 객체만 수정할 수 있습니다. 쿼리가 쓰기 트랜잭션(write transaction) 외부에서 발생하는 경우 mutableRealm.findLatest()를 사용하여 고정된 객체를 트랜잭션의 라이브 객체로 변환해야 합니다.

  3. 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction) ) 내에서 객체 를 수정합니다. 적용 차단 을 사용할 수 있습니다. 한 번에 여러 속성을 구성합니다. Realm 이 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction) )을 커밋하면 모든 변경 사항이 영역 에 자동으로 유지됩니다.

참고

문자열 또는 바이트 배열 업데이트하기

Realm은 필드 전체에서 작동하기 때문에 문자열이나 바이트 배열의 개별 요소를 직접 업데이트할 수 없습니다. 대신 전체 필드를 읽고 개별 요소를 수정한 다음 전체 필드를 트랜잭션 블록에 다시 작성해야 합니다.

Realm 객체를 업데이트하려면 업데이트하려는 특정 객체를 반환하는 필터를 사용하여 유형을 쿼리합니다. 그런 다음 객체 속성을 수정합니다.

고유 식별 정보 사용

쿼리가 올바른 객체를 반환하도록 하려면 프라이머리 키 값과 같은 고유 식별 정보로 필터링하는 것이 좋습니다.

다음 예에서는 프라이머리 키로 Frog 객체를 쿼리한 다음 nameage 속성을 업데이트합니다.

// Query and update a realm object in a single write transaction
realm.write {
val liveFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
liveFrog.name = "Michigan J. Frog"
liveFrog.age += 1
}

개별 속성을 수정하거나 내장된 객체 전체를 덮어써서 내장된 객체를 업데이트할 수 있습니다.

점 표기법으로 내장된 객체에 액세스하기

점 표기법을 사용하면 마치 일반 중첩 객체에 있는 것처럼 내장된 객체 속성에 액세스할 수 있습니다. 자세한 내용은 내장된 객체 속성별 필터링을 참조하세요.

내장된 객체에서 하나 이상의 속성을 업데이트하려면 상위 또는 내장된 객체를 가져온 다음 쓰기 트랜잭션(write transaction)에서 내장된 객체 속성을 다시 할당합니다.

다음 예에는 내장된 EmbeddedAddress 객체를 포함하는 Contact 객체가 있습니다. 여러 작업을 통해 내장된 객체 속성을 업데이트합니다:

// Modify embedded object properties in a write transaction
realm.write {
// Fetch the objects
val addressToUpdate = findLatest(address) ?: error("Cannot find latest version of embedded object")
val contactToUpdate = findLatest(contact) ?: error("Cannot find latest version of parent object")
// Update a single embedded object property directly
addressToUpdate.street = "100 10th St N"
// Update multiple properties
addressToUpdate.apply {
street = "202 Coconut Court"
city = "Los Angeles"
state = "CA"
postalCode = "90210"
}
// Update property through the parent object
contactToUpdate.address?.state = "NY"
}

내장된 객체를 완전히 덮어쓰려면 쓰기 트랜잭션(write transaction)에서 새 내장된 객체 인스턴스를 상위 속성에 할당합니다. 이렇게 하면 기존 내장된 객체가 삭제됩니다.

다음 예에는 내장된 EmbeddedAddress 객체를 포함하는 Contact 객체가 있습니다. 새 EmbeddedAddress 객체를 정의하고 이를 상위 속성에 할당합니다:

realm.write {
val parentObject = query<Contact>("_id == $0", PRIMARY_KEY_VALUE).find().first()
val newAddress = EmbeddedAddress().apply {
propertyOwner = Contact().apply { name = "Michigan J. Frog" }
street = "456 Lily Pad Ln"
country = EmbeddedCountry().apply { name = "Canada" }
}
// Overwrite the embedded object with the new instance (deletes the existing object)
parentObject.address = newAddress
}

영역에서 여러 객체를 업데이트할 수도 있습니다:

  1. 영역 을 사용하여 객체 컬렉션 에 대한 Realm을 쿼리합니다 . 쿼리().

  2. realm.write() 로 쓰기 트랜잭션(write transaction)을 엽니다. 또는 realm.writeBlocking().

  3. 쿼리에서 반환된 RealmResults 세트의 요소를 업데이트합니다.

val tadpoles = realm.query<Frog>("age <= $0", 2)
for (tadpole in tadpoles.find()) {
realm.write {
findLatest(tadpole)?.name = tadpole.name + " Jr."
}
}

객체 유형을 정의하는 방식에 따라 특수한 Realm별 유형 속성이 있을 수 있습니다.

다음 Realm API 함수를 사용하여 MutableRealmInt 속성 값을 업데이트할 수 있습니다:

  • increment()

  • decrement()

  • set()

이러한 메소드는 변경된 값으로 MutableRealmInt 속성을 반환합니다.

set() 연산자 주의해서 사용

set() 연산자는 increment() 또는 decrement()에 대한 모든 이전 호출을 덮어씁니다. 사용 사례에 따라 퍼지 카운팅이 허용되는 경우를 제외하고 set()increment() 또는 decrement()를 혼합하지 않는 것이 좋습니다.

Realm API 함수 외에도 Kotlin의 표준 라이브러리에서 제공하는 것과 유사한 다음 연산자 및 접두사 함수 설정하다 를 사용할 수도 Long 있습니다. 의 경우:

  • 단항 접두사 연산자: unaryPlus, unaryMinus

  • 증가 및 감소 연산자: inc, dec(incrementdecrement와 혼동하지 말 것)

  • 산술 연산자: plus, minus, times, div, rem

  • 등호 연산자: equals

  • 비교 연산자: compareTo

  • Bitwise functions: shl, shr, ushr, and, or, xor, inv

하지만 이러한 연산자와 중위 함수는 해당 연산자와 중위 함수가 호출된 인스턴스를 변경하지 않습니다. 대신 작업 결과와 함께 관리되지 않는 새 인스턴스를 반환합니다.

중요

Realm 메서드만 변이된 값 생성

값이 변경되는 유일한 작업은 Realm API 함수인 increment, decrementset입니다. incdec를 포함한 다른 모든 연산은 새 값을 가진 관리되지 않는 인스턴스를 반환합니다.

다음 예시에서는 increment(), decrement()set() 연산을 사용하여 MutableRealmInt 속성을 업데이트합니다:

// Open a write transaction
realm.write {
// Get the live object
val frog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
val counter: MutableRealmInt? = frog.fliesEaten
counter?.get() // 1
// Increment the value of the MutableRealmInt property
// ** Note use of decrement() with negative value **
counter?.increment(0) // 1
counter?.increment(5) // 6
counter?.decrement(-2) // 8
// Decrement the value of the MutableRealmInt property
// ** Note use of increment() with negative value **
counter?.decrement(0) // 8
counter?.decrement(2) // 6
counter?.increment(-1) // 5
// Set the value of the MutableRealmInt property
// ** Use set() with caution **
counter?.set(0)// 0
}

RealmAny 속성은 변경할 수 없습니다. RealmAny 값을 업데이트 하려면 원하는 값과 유형을 사용하여 속성 의 새 인스턴스 를 만들어야 합니다. RealmAny 속성 추가에 대한 자세한 내용 은 RealmAny(혼합) 속성 만들기를 참조하세요.

또한 RealmAny 속성에서 값을 추출하려면 반드시 저장된 유형을 알아야 합니다 . 잘못된 유형으로 getter 메서드를 호출하면 Realm에서 예외가 발생합니다.

조건 표현식으로 다형성 처리하기

값을 추출하려면 저장된 유형을 알아야 하므로 when 표현식을 사용하여 RealmAny 유형과 가능한 내부 값 클래스를 처리하는 것이 좋습니다.

val favoriteThings = frog.favoriteThings
when (favoriteThings.type) {
INT -> rating(favoriteThings.asInteger())
STRING -> description(favoriteThings.asString())
BYTE_ARRAY -> image(favoriteThings.asByteArray())
// Handle other possible types...
else -> {
// Debug or a perform default action
Log.d("ExampleHandler", "Unhandled type: ${favoriteThings.type}")
}
}

다음 예제에서는 각 목록 요소의 새 인스턴스를 만들어 RealmAny 속성 목록이 포함된 Frog 객체를 업데이트합니다.

// Find favoriteThing that is an Int
// Convert the value to Double and update the favoriteThing property
realm.write {
val kermit = query<Frog>().find().first()
val realmAny: RealmList<RealmAny?> = kermit.favoriteThings
for (i in realmAny.indices) {
val thing = realmAny[i]
if (thing?.type == RealmAny.Type.INT) {
val intValue = thing.asInt()
val doubleValue = intValue.toDouble()
realmAny[i] = RealmAny.create(doubleValue)
}
}
}
// Overwrite all existing favoriteThing properties
// ** Null clears the property value **
realm.write {
val frog = query<Frog>().find().first()
val realmAny: RealmList<RealmAny?> = frog.favoriteThings
realmAny[0] = RealmAny.create("sunshine")
realmAny[1] = RealmAny.create(Frog().apply { name = "Kermit Sr." })
realmAny[2] = null
}

참고

null로 RealmAny 속성 값 지우기

nullRealmAny 속성에 직접 할당하여 현재 값을 제거할 수 있습니다.

객체 유형을 정의하는 방식에 따라 다음의 지원되는 컬렉션 유형 중 하나로 정의된 속성이 있을 수 있습니다.

  • RealmList

  • RealmSet

  • RealmDictionary

컬렉션은 변경 가능하며 해당 내장 Kotlin 클래스로 지원됩니다. 쓰기 트랜잭션(write transaction) 내에서 컬렉션의 요소를 추가하고 제거할 수 있습니다.

컬렉션 변경 사항 수신

변경 사항을 수신하도록 알림 처리기를 등록할 수 있습니다. 자세한 내용은 컬렉션 변경 수신자 등록을 참조하세요.

Kotlin MutableList와 마찬가지로 RealmList의 요소를 업데이트 할 수 있습니다.

다음 예시에서는 기존 Frog 객체에 대해 RealmList 요소를 업데이트합니다:

realm.write {
// Get the live object
val realmList = query<Frog>("name = $0", "Kermit").first().find()!!.favoritePonds
realmList[0].name = "Picnic Pond"
realmList.set(1, Pond().apply { name = "Big Pond" })
}

RealmList 요소 추가 및 제거에 대한 자세한 내용은 RealmList 만들기RealmList에서 요소 제거를 참조하세요.

Kotlin MutableSet 와 마찬가지로 RealmSet에서 요소를 추가, 업데이트 및 제거할 수 있습니다.

다음 예에서는 기존 Frog 객체의 RealmSet 요소를 반복하고 업데이트합니다.

// Find a frog in the realm
val kermit = realm.query<Frog>("name = $0", "Kermit").find().first()
val realmSet = kermit.favoriteSnacks
// Update the name of each snack in the set
for (snack in realmSet) {
realm.write {
findLatest(snack)?.name = snack.name.uppercase()
}
}
realm.write {
// Find all frogs who like rain
val frogsWhoLikeRain = realm.query<Frog>("favoriteWeather CONTAINS $0", "rain").find()
// Add thunderstorms to their favoriteWeather set
for (frog in frogsWhoLikeRain) {
val latestFrog = findLatest(frog)
latestFrog?.favoriteWeather?.add("thunderstorms")
}
}

RealmSet 요소 추가 및 제거에 대한 자세한 내용은 RealmSet 속성 만들기RealmSet에서 요소 제거를 참조하세요.

Kotlin MutableMap과 마찬가지로 RealmDictionary에서 키와 값을 업데이트할 수 있습니다 .

다음 예시에서는 다음을 업데이트합니다. RealmDictionary

// Find frogs who have forests with favorite ponds
val thisFrog = realm.query<RealmDictionary_Frog>("favoritePondsByForest.@count > 1").find().first()
// Update the value for a key if it exists
if (thisFrog.favoritePondsByForest.containsKey("Hundred Acre Wood")) {
realm.write {
findLatest(thisFrog)?.favoritePondsByForest?.set("Lothlorien", "Lily Pad Pond")
}
}
// Add a new key-value pair
realm.write {
findLatest(thisFrog)?.favoritePondsByForest?.put("Sherwood Forest", "Miller Pond")
}

RealmDictionary 항목 추가 및 제거에 대한 자세한 내용은 사전 속성 만들기사전 키/값 제거를 참조하세요.

객체 유형을 정의하는 방법에 따라 다른 Realm 객체를 참조하는 속성이 있을 수 있습니다. 이는 to-one, to-many 또는 역관계일 수 있습니다.

한 Realm 객체를 다른 Realm 객체 내에 직접 포함하여 EmbeddedRealmObject 유형의 중첩 데이터 구조를 만들 수도 있습니다. 자세한 내용은 이 페이지 의 내장된 객체 업데이트 섹션을 참조하세요.

다른 속성을 업데이트하는 것과 같은 방식으로 관계를 정의하는 속성을 수정하여 영역의 객체 간 관계를 업데이트할 수 있습니다.

다음 예시에서는 단일 Pond 객체를 참조하는 favoritePond 속성과 다른 Frog 객체를 참조하는 bestFriend 속성을 가진 Frog 객체가 있습니다:

realm.write {
val kermit = query<Frog>("name == $0", "Kermit").find().first()
// Update a property on the related object
kermit.favoritePond?.name = "Big Pond"
// Assign a new related object
val newBestFriend = Frog().apply { name = "Froggy Jr." }
kermit.bestFriend = newBestFriend
}

다른 컬렉션을 업데이트하는 것과 같은 방식으로 to-many 관계를 업데이트할 수 있습니다. 이 페이지의 컬렉션 속성 업데이트 섹션을 참조하세요.

다음 예시에서는 Frog 객체 집합을 참조하는 frogsThatLiveHere 속성과 Pond 객체 목록을 참조하는 nearByPonds 속성을 가진 Forest 객체가 있습니다:

realm.write {
val forest = query<Forest>().find().first()
// Update a property on a related object in the set
forest.frogsThatLiveHere.first().name = "Kermit Sr."
// Add a new related object to the list
forest.frogsThatLiveHere.add(Frog().apply { name = "Froggy Jr." })
}

역관계에 있는 객체에 액세스하고 업데이트할 수 있습니다. 그러나 역링크 컬렉션 자체를 직접 수정할 수는 없습니다. 대신 Realm은 관련 객체를 수정할 때 암시적 관계를 자동으로 업데이트합니다. 자세한 내용은 역관계 정의를 참조하세요.

다음 예시에는 Post 하위 객체 목록을 참조하는 역링크 posts 속성이 있는 상위 User 객체가 있습니다. 역링크를 통해 상위 및 하위 객체의 속성을 업데이트합니다:

realm.write {
// Update child objects through the parent
val parent = query<User>().find().first()
parent.posts[0].title = "Forest Life Vol. 2"
parent.posts.add(Post().apply { title = "Forest Life Vol. 3" })
// Update child objects (Realm automatically updates the backlink collection)
val child = query<Post>("title == $0", "Top Ponds of the Year!").find().first()
child.title = "Top Ponds of the Year! Vol. 2"
assertEquals("Top Ponds of the Year! Vol. 2", parent.posts[1].title)
// Update the parent object through the child
child.user[0].name = "Kermit Sr."
// ** You CANNOT directly modify the backlink collection **
val readOnlyBacklink: RealmResults<User> = child.user
}

객체 를 Realm 에 업서트하려면 새 객체 를 만들 때와 마찬가지로 업서트() 을 사용하여 기본 키 가 있는 객체 를 삽입하고 영역 매개 변수를 전달 하여 SDK가 동일한 기본 키 를 가진 기존 객체를 처리하는 방법을 지정합니다.

  • UpdatePolicy.ALL: 동일한 프라이머리 키로 식별된 모든 기존 객체의 모든 속성을 업데이트합니다.

  • UpdatePolicy.ERROR (기본값): 기존 객체 업데이트를 허용하지 않고 동일한 프라이머리 키를 가진 객체가 이미 존재하는 경우 예외를 발생시킵니다. 업데이트 정책을 지정하지 않으면 Realm은 기본적으로 이 정책을 사용합니다.

업데이트 정책에 따라 다음이 발생할 수 있습니다:

  • 프라이머리 키와 일치하는 객체가 없으면 SDK는 새 객체를 삽입합니다.

  • 동일한 프라이머리 키를 가진 객체가 이미 존재하는 경우, SDK는 다음을 수행합니다:

    • 동일한 프라이머리 키로 식별된 모든 기존 객체의 모든 속성을 업데이트합니다. 속성이 동일한 값으로 업데이트되었더라도 변경 수신자에서 속성이 업데이트된 것으로 표시된다는 점에 유의합니다.

    • 객체가 이미 영역에 존재한다는 것을 나타내는 예외가 발생합니다.

다음 예시에서는 UpdatePolicy.ALL이 있는 영역에 이미 존재하는 프라이머리 키가 있는 Frog 객체를 삽입하고 객체가 성공적으로 업서트되었는지 확인합니다:

realm.write {
val existingFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
assertEquals(existingFrog.name, "Kermit")
// Use copyToRealm() to insert the object with the primary key
// ** UpdatePolicy determines whether to update or throw an error if object already exists**
copyToRealm(Frog().apply {
_id = PRIMARY_KEY_VALUE
name = "Wirt"
age = 4
species = "Greyfrog"
owner = "L'oric"
}, UpdatePolicy.ALL)
val upsertFrog = query<Frog>("_id == $0", PRIMARY_KEY_VALUE).find().first()
assertEquals(upsertFrog.name, "Wirt")
}

돌아가기

읽기