Esta página describe los conceptos de transacciones de escritura y objetos administrados en un reino. A continuación, explica cómo crear y persistir un nuevo objeto en un reino local o sincronizado mediante el SDK de Kotlin. Para obtener más información sobre los objetos de reino y cómo definirlos, consulte Objetos de reino.
Puedes crear objetos cuyo tipo esté incluido en el esquema del dominio al abrirlo. Para obtener más información, consulta "Abrir un dominio" o "Abrir un dominio sincronizado".
Nota
Escribir en un reino sincronizado
La sintaxis para escribir un nuevo objeto en un dominio es la misma para un dominio local o sincronizado. Sin embargo, existen consideraciones adicionales que determinan si la operación de escritura en un dominio sincronizado se realiza correctamente. Para obtener más información, consulte Escribir datos en un dominio sincronizado - SDK de Kotlin.
Transacciones de escritura
Realm gestiona las escrituras en términos de transacciones. Todas las escrituras deben ocurrir dentro de una transacción. Una transacción es una lista de operaciones de lectura y escritura que Realm trata como una sola operación indivisible: o todas las operaciones se ejecutan correctamente o ninguna de las operaciones de la transacción tiene efecto.
Realm representa cada transacción como una función de devolución de llamada que contiene cero o más operaciones de lectura y escritura. Para ejecutar una transacción, se define una devolución de llamada de transacción y se pasa al dominio.
Método write() o writeBlocking(). Con esta devolución de llamada, puede acceder a una instancia de MutableRealm y luego crear, leer, actualizar y eliminar objetos dentro del dominio. El dominio mutable representa el estado de escritura de un archivo de dominio. Los dominios mutables se proporcionan y administran automáticamente a través de
realm.write o métodos realm.writeBlocking.
Un dominio solo permite una transacción de escritura abierta a la vez. El dominio bloquea otras escrituras en otros subprocesos hasta que se complete la transacción abierta en el dominio mutable. Por lo tanto, no existe una condición de carrera al leer valores del dominio dentro de una transacción.
Cuando haya terminado su transacción, Realm la confirmará o la cancelará:
Cuando Realm confirma una transacción, escribe todos los cambios en el disco. En el caso de los dominios sincronizados, el SDK pone el cambio en cola para su sincronización con el backend.
Cuando Realm cancela una transacción de escritura o una operación en la transacción provoca un error, se descartan todos los cambios.
Nota
Objetos congelados
Los objetos devueltos por un cierre de escritura se convierten en objetos congelados al completarse la transacción de escritura. Para más información, consulte Arquitectura congelada - SDK de Kotlin.
Objetos administrados y no administrados
Las API de Realm pueden referirse a objetos como administrados o no administrados. Al crear un objeto Realm con el SDK de Kotlin, este no está administrado hasta que se copia a un realm, lo que crea una instancia administrada.
Los objetos administrados son objetos de dominio que persisten en un dominio. Solo se puede acceder a ellos desde un dominio abierto. Pueden actualizarse con cambios en las transacciones de escritura mientras dicho dominio permanezca abierto. Los objetos administrados están vinculados a la instancia del dominio desde la que se originaron y no pueden escribirse en otro.
Puedes usar las API de Realm con objetos gestionados. Por ejemplo, los objetos gestionados pueden tener relaciones con otros objetos y ser observados para detectar cambios. También se puede crear una copia no gestionada de un objeto gestionado. Consulta la sección Crear una copia no gestionada de un objeto Realm o colección en esta página.
Los objetos no administrados son instancias de objetos Realm que se comportan como objetos Kotlin normales, pero no se almacenan en un realm. Todos los objetos Realm no se administran hasta que se copian a un realm mediante una transacción de escritura. No se pueden usar las API de Realm con objetos no administrados ni observar cambios en ellos.
Tip
Puedes comprobar si un objeto está administrado con el método isManaged().
Crear un objeto de reino
Antes de crear un nuevo objeto y persistirlo en el dominio, debe definir un nuevo tipo de objeto. A continuación, incluya ese tipo de objeto en el esquema del dominio al abrirlo.
Importante
Los tipos de objetos deben estar en su esquema
Solo se pueden guardar objetos cuyo tipo de objeto Realm está incluido en el esquema realm. Si intentas hacer referencia o guardar un objeto de un tipo de objeto Realm que no está en tu esquema, Realm devolverá un error de validación de esquema.
Para crear un nuevo objeto y persistirlo en el reino:
Abra una transacción de escritura con realm.write() o realm.writeBlocking().
Cree una instancia de un objeto no administrado con el constructor de la clase. Puede usar un bloque de aplicación. para configurar múltiples propiedades a la vez.
Pase la instancia del objeto no administrado a copyToRealm() para conservar los datos del objeto en el dominio. Este método devuelve una instancia administrada activa del objeto.
Importante
Los objetos asimétricos utilizan Insert()
Los objetos asimétricos son objetos especiales de solo escritura que no persisten en el dominio. No
copyToRealm()usan. En su lugar, se pasa la instancia del objeto asimétrico alinsert()método de extensión dentro de una transacción de escritura. Consulte la sección "Crear un objeto asimétrico" en esta página para obtener más información.Trabaje con el objeto Realm persistente a través de la instancia devuelta. El objeto activo es accesible hasta que se complete la transacción de escritura. Tenga en cuenta que esto no aplica a los objetos asimétricos, que son de solo escritura y no persisten en el dominio.
También puedes insertar un objeto en un reino usando criterios específicos. Para más información, consulta Insertar un objeto en un reino.
Crear un objeto de reino
Para crear una nueva instancia de RealmObject, crea un nuevo objeto de tipo de objeto realm.
En el siguiente ejemplo, instanciamos un objeto Frog en un bloque realm.write() y luego pasamos el objeto instanciado a copyToRealm() para devolver una instancia administrada:
// Open a write transaction realm.write { // Instantiate a new unmanaged Frog object val unmanagedFrog = Frog().apply { name = "Kermit" age = 42 owner = "Jim Henson" } assertFalse(unmanagedFrog.isManaged()) // Copy the object to realm to return a managed instance val managedFrog = copyToRealm(unmanagedFrog) assertTrue(managedFrog.isManaged()) // Work with the managed object ... }
Crear un objeto incrustado
Para crear una nueva instancia de EmbeddedRealmObject, asigna una instancia de un tipo de objeto incrustado a una propiedad del objeto principal. Esto puede darse en una relación uno a uno, uno a muchos, o inversa, dependiendo de cómo se haya definido el objeto incrustado dentro del tipo de objeto Realm. Para obtener más información, consulta Definir un objeto incrustado.
Nota
Los objetos incrustados deben crearse dentro de un objeto principal
Un objeto incrustado requiere un objeto padre y no puede existir como un objeto Realm independiente.
Los objetos incrustados tienen propiedad estricta con su objeto principal. Después de crear el objeto incrustado,no se puede reasignar a otro objeto principal ni compartirlo entre varios objetos principales.
En el siguiente ejemplo, instanciamos un nuevo objeto Contact con un Address incrustado, que contiene un objeto Contact y un objeto Country incrustado:
realm.write { // Instantiate a parent object with one embedded address val contact = Contact().apply { name = "Kermit" address = EmbeddedAddress().apply { propertyOwner = Contact().apply { name = "Mr. Frog" } street = "123 Pond St" country = EmbeddedCountry().apply { name = "United States" } } } // Copy all objects to the realm to return managed instances copyToRealm(contact) }
También instanciamos un nuevo objeto Business con una lista de objetos Address incrustados, que también contienen objetos Contact y objetos Country incrustados:
realm.write { // Instantiate a parent object with multiple embedded addresses val localOffice = EmbeddedAddress().apply { propertyOwner = Contact().apply { name = "Michigan J. Frog" } street = "456 Lily Pad Ln" country = EmbeddedCountry().apply { name = "United States" } } val remoteOffice = EmbeddedAddress().apply { propertyOwner = Contact().apply { name = "Mr. Toad" } street = "789 Leaping Frog Ave" country = EmbeddedCountry().apply { name = "Ireland" } } val business = Business().apply { name = "Big Frog Corp." addresses = realmListOf(localOffice, remoteOffice) } // Copy all objects to the realm to return managed instances copyToRealm(business) }
Crear un objeto asimétrico
Nuevo en la versión 1.10.0.
A diferencia de otros objetos de Realm,no se utiliza el copyToRealm() método para crearlo. Esto se debe a que los objetos asimétricos son de solo escritura: no se almacenan en el dominio. En su lugar, se utiliza un insert() método de extensión especial para insertarlos en el dominio.
Para crear una nueva AsymmetricRealmObject instancia, cree una instancia de un nuevo objeto de un tipo de objeto asimétrico usando insert().
En el siguiente ejemplo, instanciamos un nuevo objeto WeatherSensor y lo pasamos a insert() dentro de una transacción de escritura:
// Open a write transaction realm.write { // Create a new asymmetric object val weatherSensor = WeatherSensor().apply { deviceId = "WX1278UIT" temperatureInFarenheit = 6.7F barometricPressureInHg = 29.65F windSpeedInMph = 2 } // Insert the object into the realm with the insert() extension method insert(weatherSensor) // WeatherSensor object is inserted into the realm, then synced to the // App Services backend. You CANNOT access the object locally because it's // deleted from the local realm after sync is complete. }
Una vez insertado, el objeto asimétrico se sincroniza con el backend de App Services y la base de datos Atlas vinculada.No se puede acceder a los datos administrados localmente, añadirlos o eliminarlos de un dominio, ni consultarlos. Para obtener información sobre cómo usar objetos asimétricos en su aplicación, consulte "Transmitir datos a Atlas - SDK de Kotlin".
Crear propiedades de reino
Dependiendo de cómo defina su tipo de objeto, es posible que tenga propiedades que sean tipos especiales específicos del reino.
En el siguiente ejemplo, tenemos un tipo de objeto Frog con varias propiedades Realm:
class Frog : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" var birthdate: RealmInstant? = null var fliesEaten: MutableRealmInt? = null var favoriteThings: RealmList<RealmAny?> = realmListOf() }
Crear una propiedad RealmInstant (marca de tiempo)
Para crear una nueva instancia de objeto con una propiedad RealmInstant, cree una instancia de un objeto y pase un valor inicial a la RealmInstant propiedad usando:
RealmInstant.from(): los segundos y nanosegundos desde la época de Unix
RealmInstant.now(): los segundos y nanosegundos desde la época de Unix hasta ahora
Para obtener más información sobre el RealmInstant tipo, consulte RealmInstant (marca de tiempo).
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con una propiedad birthdate y pasamos un valor inicial a RealmInstant.from():
realm.write { // Instantiate a new unmanaged Frog object with a RealmInstant property val frog = Frog().apply { name = "Kermit" // Set an initial value with RealmInstant.from() or RealmInstant.now() birthdate = RealmInstant.from(1_577_996_800, 0) } // Copy the object to the realm to return a managed instance copyToRealm(frog) }
Crear una propiedad MutableRealmInt (Counter)
Para crear una nueva instancia de objeto con una propiedad MutableRealmInt, cree una instancia de un objeto y pase un valor inicial a la MutableRealmInt propiedad mediante MutableRealmInt.create(). Para obtener más información sobre el MutableRealmInt tipo, consulte MutableRealmInt (Counter).
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con una propiedad fliesEaten y pasamos un valor inicial a MutableRealmInt.create():
realm.write { // Instantiate a new unmanaged Frog object with a MutableRealmInt property val frog = Frog().apply { name = "Michigan J. Frog" // Set an initial value with MutableRealmInt.create() fliesEaten = MutableRealmInt.create(200) } // Copy the object to the realm to return a managed instance copyToRealm(frog) }
Crear una propiedad RealmAny (Mixta)
Para crear una nueva instancia de objeto con una propiedad polimórfica RealmAny, cree una instancia de un objeto y pase un valor inicial de un tipo compatible a la RealmAny propiedad mediante RealmAny.create(). Para obtener una lista de los tipos de valores que RealmAny puede contener, consulte RealmAny (Mixto).
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con una lista favoriteThings de tipo RealmAny y pasamos los valores iniciales a RealmAny.create():
realm.write { // Instantiate a new unmanaged Frog object with a RealmAny property val frog = Frog().apply { name = "Kermit" // Set initial values with RealmAny.create() favoriteThings = realmListOf( RealmAny.create(42), RealmAny.create("rainbows"), RealmAny.create(Frog().apply { name = "Kermit Jr." }) ) } // Copy the object to the realm to return a managed instance copyToRealm(frog) }
Después de crear el objeto, debe conocer el tipo de valor almacenado para trabajar con la propiedad RealmAny. Para aprender cómo actualizar las propiedades RealmAny después de crear el objeto, consulta Actualiza una propiedad RealmAny (Mixta).
Crear propiedades de colección
Dependiendo de cómo defina su tipo de objeto, es posible que tenga propiedades que estén definidas como uno de los siguientes tipos de colección compatibles:
RealmListRealmSetRealmDictionary
Para obtener más información, consulte Definir propiedades de colección.
Las colecciones son mutables: puedes agregar y eliminar elementos en una colección dentro de una transacción de escritura.
Las colecciones pueden contener objetos administrados y no administrados. Al copiar una colección al dominio, se crea una instancia administrada de la colección y de todos sus elementos, incluidos los no administrados. Las colecciones no administradas se comportan como sus clases Kotlin correspondientes y no se persisten en el dominio.
Tip
Escuchar los cambios en una colección creada
Después de crear una colección, puede registrar un controlador de notificaciones para detectar cambios. Para obtener más información, consulte Registrar un controlador de notificaciones de cambios de colección.
Crear una RealmList
Para crear una nueva instancia de objeto con una propiedad RealmList, cree una instancia de un objeto y pase cualquier valor de un tipo compatible a la RealmList propiedad. Para obtener una lista de los tipos de valores que RealmList puede contener, consulte RealmList.
Puedes instanciar una lista no administrada con realmListOf() o pasarle elementos mediante list.add(), list.addAll() o list.set(). La lista no se administra hasta que la copies al dominio.
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con valores iniciales para varias propiedades RealmList:
realm.write { // Instantiate a new unmanaged Frog object with a RealmList property val frog = Frog().apply { name = "Kermit" // Set values for each unmanaged list favoritePonds.addAll(realmListOf( Pond().apply { name = "Picnic Pond" }, Pond().apply { name = "Big Pond" } )) favoriteForests.add(EmbeddedForest().apply { name = "Hundred Acre Wood" }) favoriteWeather = realmListOf("rain", "snow") } // Copy all objects to the realm to return managed instances copyToRealm(frog) }
Crear una propiedad RealmSet
Para crear una nueva instancia de objeto con una propiedad RealmSet, cree una instancia de un objeto y pase cualquier valor de un tipo compatible a la RealmSet propiedad. Para obtener una lista de los tipos válidos que RealmSet puede contener, consulte RealmSet.
Puedes instanciar un conjunto no administrado con realmSetOf() o pasarle elementos mediante set.add() o set.addAll(). El conjunto no se administra hasta que lo copies al dominio.
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con valores iniciales para las propiedades establecidas favoriteSnacks y favoriteWeather:
realm.write { // Instantiate a new unmanaged Frog object with RealmSet properties val frog = Frog().apply { name = "Kermit" // Set initial values to each unmanaged set favoriteSnacks.addAll(setOf( Snack().apply { name = "flies" }, Snack().apply { name = "crickets" }, Snack().apply { name = "worms" } )) favoriteWeather.add("rain") } // Copy all objects to the realm to return managed instances copyToRealm(frog) }
Crear una propiedad de diccionario
Para crear una nueva instancia de objeto con una propiedad RealmDictionary, cree una instancia de un objeto y pase cualquier par clave-valor de un tipo compatible a la RealmDictionary propiedad. RealmDictionary solo acepta una String clave, pero los valores pueden ser de tipos distintos de cadenas. Para obtener una lista de tipos válidos, consulte RealmMap/RealmDictionary.
Puedes instanciar un diccionario no administrado con realmDictionaryOf() o realmDictionaryEntryOf(). También puedes pasar valores clave con put() o putAll(). El diccionario no se administra hasta que lo copies al dominio.
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con valores clave iniciales para varias propiedades del diccionario:
realm.write { val frog = Frog().apply { name = "Kermit" // Set initial key-values to each unmanaged dictionary favoriteFriendsByPond = realmDictionaryOf( "Picnic Pond" to Frog().apply { name = "Froggy Jay" }, "Big Pond" to Frog().apply { name = "Mr. Toad" } ) favoriteTreesInForest["Maple"] = EmbeddedForest().apply { name = "Hundred Acre Wood" } favoritePondsByForest.putAll( mapOf( "Silver Pond" to "Big Forest", "Big Lake" to "Elm Wood", "Trout Pond" to "Sunny Wood" ) ) } // Copy all objects to the realm to return managed instances copyToRealm(frog) }
Realm no permite el uso de caracteres . o $ en las claves de mapa. Puedes usar la codificación y decodificación porcentual para almacenar una clave de mapa que contenga uno de estos caracteres no permitidos.
// Percent encode . or $ characters to use them in map keys val mapKey = "Hundred Acre Wood.Northeast" val encodedMapKey = "Hundred Acre Wood%2ENortheast"
Crear una propiedad de relación
Dependiendo de cómo defina su tipo de objeto, podría tener propiedades que hagan referencia a otro objeto Realm. Esta puede ser una relación de uno a uno, de muchos a muchos o inversa. Para obtener más información sobre cómo definir relaciones en su modelo de objetos, consulte Definir una relación.
También puedes incrustar un objeto Realm directamente dentro de otro para crear una estructura de datos anidada con un tipo EmbeddedRealmObject. Para crear una relación con un objeto incrustado, consulta la sección Crear un objeto incrustado en esta página.
Crea una relación de uno a uno
Para crear una nueva instancia de objeto con una propiedad de relación de uno a uno, cree una instancia de ambos objetos y pase el objeto referenciado a la propiedad de relación.
En el siguiente ejemplo, instanciamos un nuevo objeto Frog con una propiedad favoritePond que referencia un objeto Pond y una propiedad bestFriend que referencia otro objeto Frog:
realm.write { // Instantiate a new unmanaged Frog object with to-one // relationship with a Realm object val frog = Frog().apply { name = "Kermit" age = 12 favoritePond = Pond().apply { name = "Picnic Pond" } bestFriend = Frog().apply { name = "Froggy Jay" } } // Copy all objects to the realm to return managed instances copyToRealm(frog) }
Crear una relación de muchos
Para crear una nueva instancia de objeto con una propiedad de relación de varios, cree una instancia de todos los objetos y pase cualquier objeto referenciado a la propiedad de colección de relaciones.
En el siguiente ejemplo, instanciamos un nuevo objeto Forest con una propiedad frogsThatLiveHere que hace referencia a un conjunto de Frog objetos y una propiedad nearByPonds que hace referencia a una lista de Pond objetos:
realm.write { // Instantiate a new unmanaged Forest object with to-many // relationship with multiple Realm objects val forest = Forest().apply { name = "Froggy Forest" frogsThatLiveHere = realmSetOf( Frog().apply { name = "Kermit" }, Frog().apply { name = "Froggy Jay" } ) nearbyPonds = realmListOf( Pond().apply { name = "Small Picnic Pond" }, Pond().apply { name = "Big Pond" } ) } // Copy all objects to the realm to return managed instances copyToRealm(forest) }
Crear una relación inversa
Para crear una nueva instancia de objeto con una propiedad de relación inversa, cree una instancia del objeto padre y pase cualquier objeto hijo referenciado a la propiedad de colección de vínculo de retroceso.
En el siguiente ejemplo, se instanciará un objeto User nuevo con una propiedad de vínculos inversos posts que hace referencia a una lista de objetos Post:
realm.write { // Instantiate a new unmanaged User object with to-many // relationship with multiple Realm objects val post1 = Post().apply { title = "Forest Life" } val post2 = Post().apply { title = "Top Ponds of the Year!" } val user = User().apply { name = "Kermit" posts = realmListOf(post1, post2) } // Copy all objects to the realm to return managed instances copyToRealm(user) }
Después de crear el objeto, puede acceder a la propiedad de colección de vínculos de retroceso para obtener los objetos secundarios, pero no puede modificar directamente el vínculo de retroceso. Para obtener más información, consulte Actualizar una relación inversa.
Crear una copia no administrada de un objeto o colección de Realm
Puede crear una copia no administrada de un objeto o colección administrados pasándola a copyFromRealm(). Este método devuelve una copia no administrada en memoria del objeto o colección. Para las colecciones, se trata de una copia profunda que incluye todos los objetos referenciados hasta el depth especificado.
En el siguiente ejemplo, creamos una copia no administrada de un objeto Pond administrado existente que contiene una lista de dos objetos Frog. Tras copiar el objeto del dominio, confirmamos que la copia no está administrada y contiene ambos objetos Frog referenciados:
realm.writeBlocking { // Fetch the managed object you want to copy val managedPond = query<Pond>("name == $0", "Big Pond").find().first() assertTrue(managedPond.isManaged()) // Create an unmanaged copy of the object val unmanagedPond = copyFromRealm(managedPond) assertFalse(unmanagedPond.isManaged()) Log.v("Unmanaged pond name: ${unmanagedPond.name}") // Confirm the unmanaged copy contains all elements // in the copied object's RealmList val unmanagedFrogs = unmanagedPond.frogsThatLiveHere assertFalse(unmanagedFrogs[0].isManaged()) assertFalse(unmanagedFrogs[1].isManaged()) assertEquals(2, unmanagedFrogs.size) Log.v("Unmanaged frogs: ${unmanagedFrogs[0].name}, ${unmanagedFrogs[1].name}") }
Unmanaged pond name: Big Pond Unmanaged frogs: Kermit, Froggy Jay