Atualizar objetos de domínio - Kotlin SDK
Nesta página
- Atualizar operações
- Atualizar um objeto existente
- Atualizar um objeto de realm
- Atualizar um Objeto Embarcado
- Atualizar vários objetos
- Atualizar propriedades do domínio
- Atualizar uma propriedade MutableRealmInt (Contador)
- Atualizar uma propriedade RealmAny (Misto)
- Atualizar propriedades da coleção
- Atualizar um RealmList
- Atualizar um RealmSet
- Atualizar um dicionário
- Atualizar relacionamentos
- Atualizar um relacionamento entre um e outro
- Atualizar um relacionamento para muitos
- Atualizar uma relação inversa
- Fazer Upsert de um Objeto de Realm
Esta página descreve como atualizar um objeto de Realm existente em um domínio local ou sincronizado usando o Kotlin SDK. Para saber mais sobre como criar objetos em um domínio, consulte Criar objetos do Realm - Kotlin SDK.
O Realm oferece suporte a operações de atualização e upsert em objetos do Realm e objetos incorporados. Uma operação upsert insere uma nova instância de um objeto ou atualiza um objeto existente que atende a determinados critérios. Para obter mais informações, consulte a seção Upsert a Realm Object nesta página.
Você não pode atualizar objetos assimétricos. Isso ocorre porque objetos assimétricos são objetos especiais somente para gravação que não persistem no domínio. Para obter informações sobre como usar objetos assimétricos em seu aplicativo, consulte Stream Data to Atlas -Kotlin SDK.
Observação
Escreva para um domínio sincronizado
A sintaxe para atualizar um objeto em um domínio é a mesma para um domínio local ou sincronizado. No entanto, há considerações adicionais que determinam se a operação de gravação em um domínio sincronizado é bem-sucedida. Para obter mais informações, consulte Gravar dados em um realm sincronizado - Kotlin SDK.
Atualizar operações
Todas as operações que modificam um realm - inclusive as operações de atualização e upsert, devem ser realizadas dentro de uma transação de gravação. As transações de gravação são passadas para o método write() ou writeBlocking() do realm. Nesse retorno de chamada, você pode acessar uma instância MutableRealm e, em seguida, atualizar objetos dentro do realm. Para obter mais informações sobre transações de gravação e como o realm as trata, consulte Transações de gravação.
Além disso, você só pode modificar objetos ativos, que só são acessíveis dentro de uma transação de gravação. Você pode converter um objeto congelado em um objeto ativo em uma transação com mutableRealm.findLatest().
Exemplo
Converter objeto congelado antes de modificar
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 } }
Atualizar um objeto existente
Para modificar as propriedades de um objeto de Realm ou objeto incorporado armazenado em um domínio:
Abra uma transação de gravação com realm.write() ou realm.writeBlocking().
Obtenha os objetos ativos consultando o realm mutável da transação para os objetos que você deseja modificar usando query():
Especifique o tipo de objeto como um parâmetro de tipo passado para
query()
.(Opcional) Filtre o conjunto de objetos retornados especificando uma query. Se você não incluir um filtro de query, retornará todos os objetos do tipo especificado. Para obter mais informações sobre a query com o Kotlin SDK, consulte Read Realm Objects - Kotlin SDK.
Importante
Objetos devem estar ao vivo
Você só pode modificar objetos ao vivo. Se sua query ocorrer fora da transação de escrita, você deverá converter os objetos congelados em objetos ativos na transação com
mutableRealm.findLatest()
.Modifique o objeto dentro da transação de gravação. Você pode usar um bloco de aplicação para configurar várias propriedades de uma só vez. Todas as alterações são automaticamente mantidas no Realm quando o Realm confirma a transação de gravação.
Observação
Atualizando Strings ou Matrizes de Bytes
Como o Realm opera em campos como um todo, não é possível atualizar diretamente elementos individuais de strings ou arrays de bytes. Em vez disso, é necessário ler o campo inteiro, fazer a modificação em elementos individuais e, em seguida, gravar o campo inteiro novamente em um bloco de transação.
Atualizar um objeto de realm
Para atualizar um objeto de Realm, consulte o tipo usando um filtro que retorna o objeto específico que você deseja atualizar. Em seguida, modifique as propriedades do objeto.
Dica
Usar informações de identificação exclusivas
Recomendamos filtrar com informações de identificação exclusivas, como um valor de chave primária, para garantir que sua query retorne o objeto correto.
No exemplo a seguir, executamos query de um objeto Frog
por chave primária e, em seguida, atualizamos as propriedades name
e age
:
// 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 }
Atualizar um Objeto Embarcado
Você pode atualizar um objeto incorporado modificando propriedades individuais ou substituindo todo o objeto incorporado.
Dica
Acesse objetos incorporados com notação de ponto
Você pode usar a notação de pontos para acessar as propriedades do objeto embarcado como se estivesse em um objeto normal aninhado. Para obter mais informações, consulte Filtrar por propriedade de objeto embarcado.
Para atualizar uma ou mais propriedades em um objeto incorporado, busque o objeto pai ou incorporado e reatribua as propriedades do objeto incorporado em uma transação de escrita.
No exemplo a seguir, temos um objeto Contact
que contém um objeto EmbeddedAddress
incorporado. Atualizamos as propriedades de objeto incorporadas em várias operações:
// 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" }
Para substituir completamente um objeto incorporado, atribua uma nova instância de objeto incorporado à propriedade principal em uma transação de escrita. Isso exclui o objeto incorporado existente.
No exemplo a seguir, temos um objeto Contact
que contém um objeto EmbeddedAddress
incorporado. Definimos um novo objeto EmbeddedAddress
e o atribuímos à propriedade principal:
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 }
Atualizar vários objetos
Você também pode atualizar vários objetos em um domínio:
Executar queries de um realm para uma coleção de objetos com realm.query().
Abra uma transação de gravação com realm.write() ou realm.writeBlocking().
Atualiza os elementos do conjunto de RealmResults retornados pela query.
val tadpoles = realm.query<Frog>("age <= $0", 2) for (tadpole in tadpoles.find()) { realm.write { findLatest(tadpole)?.name = tadpole.name + " Jr." } }
Atualizar propriedades do domínio
Dependendo de como você define o seu tipo de objeto, você pode ter propriedades que são tiposespeciais específicos do Realm.
Atualizar uma propriedade MutableRealmInt (Contador)
Você pode utilizar as seguintes funções de API do Realm para atualizar um valor de propriedade MutableRealmInt
:
increment()
decrement()
set()
Estes métodos retornam a propriedade MutableRealmInt
com um valor mutado.
Dica
Use o operador set() com cuidado
O operador set()
substitui quaisquer chamadas anteriores para increment()
ou decrement()
. Não recomendamos misturar set()
com increment()
ou decrement()
, a menos que a contagem difusa seja aceitável para seu caso de uso.
Além das funções da API Realm , você também pode usar o seguinte conjunto de operadores e funções infix semelhantes às fornecidas pela biblioteca padrão do Kotlin para Long
:
Operadores de prefixo unário:
unaryPlus
,unaryMinus
Operadores de aumento e decremento:
inc
,dec
(não deve ser confundido comincrement
edecrement
)Operadores aritméticos:
plus
,minus
,times
,div
,rem
Operadores de qualidade:
equals
Operadores de comparação:
compareTo
Bitwise functions:
shl
,shr
,ushr
,and
,or
,xor
,inv
No entanto, esses operadores e funções infix não mutam a instância na qual são chamados. Em vez disso, eles retornam uma nova instância não gerenciada com o resultado da operação.
Importante
Somente métodos de domínio resultam em um valor mutado
As únicas operações que resultam em um valor mutado são as funções da API do Realm: increment
, decrement
e set
. Todas as outras operações (incluindo inc
e dec
) retornam uma instância não gerenciada com um novo valor.
No exemplo seguinte, atualizamos uma propriedade MutableRealmInt
com operações increment()
, decrement()
e set()
:
// 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 }
Atualizar uma propriedade RealmAny (Misto)
As propriedades do RealmAny são imutáveis. Para atualizar um valor RealmAny
, você deve criar uma nova instância da propriedade com o valor e tipo desejados. Para mais informações sobre como adicionar propriedades do RealmAny
, consulte Criar uma propriedade RealmAny (Misto).
Adicionalmente, você deve conhecer o tipo armazenado para extrair o valor de uma propriedade RealmAny
. Se você chamar um método de getter com o tipo errado, o Realm lança uma exceção.
Dica
Lidar com polimorfismo com expressões condicionais
Como você precisa conhecer o tipo armazenado para extrair seu valor, recomendamos o uso de uma expressão when
para lidar com o tipo RealmAny
e sua possível classe de valor interna.
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}") } }
No exemplo a seguir, atualizamos um objeto Frog
que contém uma lista de propriedades do RealmAny
criando novas instâncias de cada elemento de lista:
// 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 }
Observação
Limpar um RealmQualquer valor de propriedade com nulo
Você pode atribuir null
diretamente a uma propriedade RealmAny
para remover o valor atual.
Atualizar propriedades da coleção
Dependendo de como você define seu tipo de objeto, você pode ter propriedades definidas como um dos seguintes tipos de coleção compatíveis:
RealmList
RealmSet
RealmDictionary
As coleções são mutáveis e contam com o apoio de suas classes Kotlin incorporadas correspondentes. Você pode adicionar e remover elementos em uma coleção dentro de uma transação por escrito.
Dica
Ouça as alterações em uma coleção
Você pode registrar um manipulador de notificações para ouvir as alterações. Para mais informações, consulte Registrar um Listener de Alteração de Coleção.
Atualizar um RealmList
Você pode atualizar elementos em uma RealmList como faria com uma Kotlin MutableList.
No exemplo a seguir, atualizamos os elementos RealmList
para um objeto Frog
existente:
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" }) }
Para mais informações sobre adicionar e remover elementos do RealmList
, consulte Criar uma RealmList e Remover Elementos de uma RealmList.
Atualizar um RealmSet
Você pode adicionar, atualizar e remover elementos em um RealmSet como faria com um Kotlin MutableSet.
No exemplo a seguir, iteramos e atualizamos RealmSet
elementos para objetos Frog
existentes:
// 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") } }
Para mais informações sobre adicionar e remover elementos do RealmSet
, consulte Criar uma Propriedade do RealmSet e Remover Elementos de um RealmSet.
Atualizar um dicionário
Você pode atualizar chaves e valores em um RealmDictionary como faria com um Kotlin MutableMap.
No exemplo a seguir, atualizamos um 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") }
Para obter mais informações sobre como adicionar e remover entradas do RealmDictionary
, consulte Criar uma propriedade de dicionário e Remover chaves/valores de dicionário.
Atualizar relacionamentos
Dependendo de como você define seu tipo de objeto, você pode ter propriedades que referenciam outro objeto do Realm. Isso pode ser uma relação para-um, para-muitos ou inversa.
Você também pode incorporar um objeto de Realm diretamente dentro de outro para criar uma estrutura de dados aninhada com um tipo EmbeddedRealmObject
. Para obter mais informações, consulte a seção Atualizar um objeto incorporado nesta página.
Atualizar um relacionamento entre um e outro
Você pode atualizar relações entre objetos em um território modificando as propriedades que definem a relação da mesma forma que atualizaria qualquer outra propriedade.
No exemplo a seguir, temos um objeto Frog
com uma propriedade favoritePond
que referencia um único objeto Pond
e uma propriedade bestFriend
que referencia outro objeto 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 }
Atualizar um relacionamento para muitos
Você pode atualizar relacionamentos para muitos da mesma forma que atualizaria qualquer outra coleção. Consulte a seção Atualizar propriedades da coleção nesta página.
No exemplo seguinte, temos um objeto Forest
com uma propriedade frogsThatLiveHere
que referencia um conjunto de objetos Frog
e uma propriedade nearByPonds
que referencia uma lista de objetos Pond
:
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." }) }
Atualizar uma relação inversa
Você pode acessar e atualizar objetos em um relacionamento inverso. No entanto, você não pode modificar diretamente a coleção de backlink em si. Em vez disso, o Realm atualiza automaticamente o relacionamento implícito quando você modifica quaisquer objetos relacionados. Para mais informações, consulte Definir um relacionamento inverso.
No exemplo a seguir, temos um objeto principal User
com uma propriedade backlinks posts
que faz referência a uma lista de objetos secundários Post
. Atualizamos propriedades nos objetos principal e secundário por meio do backlink:
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 }
Fazer Upsert de um Objeto de Realm
Para fazer upsert de um objeto em um realm, insira um objeto com uma chave primária usando copyToRealm(), como faria ao criar um novo objeto, e passe um parâmetro UpdatePolicy para especificar como o SDK lida com objetos existentes com a mesma chave primária:
UpdatePolicy.ALL
: Atualize todas as propriedades em quaisquer objetos existentes identificados com a mesma chave primária.UpdatePolicy.ERROR
(padrão): não permitir a atualização de objetos existentes e, em vez disso, lançar uma exceção se um objeto já existir com a mesma chave primária. Se você não especificar uma política de atualização, o Realm usará essa política por padrão.
O seguinte pode ocorrer dependendo da política de atualização:
Se não houver nenhum objeto que corresponda à chave primária, o SDK inserirá o novo objeto.
Se já existir um objeto com a mesma chave primária, o SDK:
Atualiza todas as propriedades em quaisquer objetos existentes identificados com a mesma chave primária. Observe que as propriedades são marcadas como atualizadas nos ouvintes de alterações, mesmo que a propriedade tenha sido atualizada com o mesmo valor.
Lança uma exceção indicando que um objeto já existe no domínio.
No exemplo a seguir, tentamos inserir um objeto Frog
com uma chave primária que já existe no domínio com UpdatePolicy.ALL
e confirmamos que o objeto foi inserido com sucesso:
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") }