Transacciones de escritura
Realm utiliza un motor de almacenamiento altamente eficiente para persistir objetos. Se pueden crear, actualizar y, eventualmente, eliminar objetos en un reino. Dado que estas operaciones modifican el estado del reino, se denominan escrituras.
Realm gestiona las escrituras en términos de transacciones. Una transacción es una lista de operaciones de lectura y escritura que Realm trata como una sola operación indivisible. En otras palabras, una transacción es todo o nada: o todas las operaciones de la transacción se realizan correctamente o ninguna de ellas surte efecto.
Todas las escrituras deben realizarse en una transacción.
Un dominio solo permite una transacción abierta a la vez. El dominio bloquea otras escrituras en otros subprocesos hasta que la transacción abierta se complete. Por lo tanto, no hay condición de carrera al leer valores del dominio dentro de una transacción.
Cuando finalices tu transacción, Realm la confirma o la cancela:
Cuando Realm confirma una transacción, Realm guarda todos los cambios en el disco. Para los realms sincronizados, el SDK pone en cola el cambio para la sincronización con Atlas Device Sync.
Cuando Realm cancela una transacción de escritura o una operación en la transacción provoca un error, todos los cambios se descartan (o se "revierten").
Crear un nuevo objeto
Crear un objeto
Para crear un objeto, debes instanciarlo usando el realm espacio de nombres. Mueva el objeto al reino usando el
Función Realm.add() dentro de una transacción de escritura.
Al mover un objeto a un dominio, este se consume como un valor r. Debe usar el objeto administrado para cualquier acceso u observación de datos. En este ejemplo, copiar el objeto dog al dominio lo consume como un valor r. Puede devolver el objeto administrado para seguir trabajando con él.
// Create an object using the `realm` namespace. auto dog = realm::Dog{.name = "Rex", .age = 1}; std::cout << "dog: " << dog.name << "\n"; // Open the database with compile-time schema checking. auto config = realm::db_config(); auto realm = realm::db(std::move(config)); // Persist your data in a write transaction // Optionally return the managed object to work with it immediately auto managedDog = realm.write([&] { return realm.add(std::move(dog)); });
Modelo
Para obtener más información sobre cómo modelar un objeto, consulte: Definir un nuevo tipo de objeto.
namespace realm { struct Dog { std::string name; int64_t age; }; REALM_SCHEMA(Dog, name, age) } // namespace realm
Crear un objeto incrustado
Para crear un objeto incrustado, asigne el puntero sin formato del objeto incrustado a una propiedad del objeto principal. Mueva el objeto principal al dominio mediante la función Realm.add() dentro de una transacción de escritura.
En este ejemplo, asignamos el puntero sin formato del objeto incrustado - ContactDetails * - a la propiedad del objeto incrustado del objeto padre - Business.contactDetails.
Luego, añadimos el objeto business al dominio. Esto copia los objetos business y contactDetails al dominio.
Dado que ContactDetails es un objeto incrustado, no tiene un ciclo de vida propio, independiente del objeto principal Business. Si elimina el objeto Business, también se elimina el objeto ContactDetails.
auto config = realm::db_config(); auto realm = realm::db(std::move(config)); auto contactDetails = realm::ContactDetails{ .emailAddress = "email@example.com", .phoneNumber = "123-456-7890"}; auto business = realm::Business(); business._id = realm::object_id::generate(); business.name = "MongoDB"; business.contactDetails = &contactDetails; realm.write([&] { realm.add(std::move(business)); });
Modelo
Para obtener más información sobre cómo modelar un objeto incrustado, consulte: Definir un objeto incrustado.
namespace realm { struct ContactDetails { // Because ContactDetails is an embedded object, it cannot have its own _id // It does not have a lifecycle outside of the top-level object std::string emailAddress; std::string phoneNumber; }; REALM_EMBEDDED_SCHEMA(ContactDetails, emailAddress, phoneNumber) struct Business { realm::object_id _id; std::string name; ContactDetails *contactDetails; }; REALM_SCHEMA(Business, _id, name, contactDetails) } // namespace realm
Crear un objeto con una relación de uno a uno
Para crear un objeto con una relación de uno a otro, asigne el puntero del objeto relacionado a la propiedad de relación del objeto principal. Mueva el objeto al dominio usando la función Realm.add() dentro de una transacción de escritura.
En este ejemplo, asignamos el puntero sin formato del objeto relacionado (FavoriteToy *) a la propiedad de relación del objeto principal (Dog.favoriteToy). Luego, al agregar el objeto dog al dominio, se copian tanto dog como favoriteToy.
El objeto relacionado favoriteToy tiene su propio ciclo de vida independiente del objeto principal dog. Si se borra el objeto principal, el objeto relacionado permanece.
auto config = realm::db_config(); auto realmInstance = realm::db(std::move(config)); auto favoriteToy = realm::FavoriteToy{ ._id = realm::uuid("68b696c9-320b-4402-a412-d9cee10fc6a5"), .name = "Wubba"}; auto dog = realm::Dog{ ._id = realm::uuid("68b696d7-320b-4402-a412-d9cee10fc6a3"), .name = "Lita", .age = 10, .favoriteToy = &favoriteToy}; realmInstance.write([&] { realmInstance.add(std::move(dog)); });
Opcionalmente, puede crear una relación inversa para hacer referencia al objeto principal desde el objeto relacionado. Para obtener más información, consulte: Crear un objeto con una relación inversa.
Modelo
Para obtener más información sobre cómo modelar una relación de uno a uno, consulte: Definir una relación de uno a uno.
struct FavoriteToy { realm::primary_key<realm::uuid> _id; std::string name; }; REALM_SCHEMA(FavoriteToy, _id, name) struct Dog { realm::primary_key<realm::uuid> _id; std::string name; int64_t age; // Define a relationship as a link to another SDK object FavoriteToy* favoriteToy; }; REALM_SCHEMA(Dog, _id, name, age, favoriteToy)
Crear un objeto con una relación de muchos
Para crear un objeto con una relación de varios con uno o más objetos:
Inicializar el objeto principal y los objetos relacionados
Utilice la función miembro push_back disponible para las listas de objetos Realm para agregar los punteros sin procesar de los objetos relacionados a la propiedad de lista del objeto principal
Mueva el objeto al reino usando la función Realm.add() dentro de una transacción de escritura.
En este ejemplo, agregamos los punteros sin procesar de los objetos relacionados (Employee *) a la propiedad de relación del objeto principal (Company.employees). Esto crea una conexión unidireccional entre el objeto Company y los objetos Employee.
Luego, se agrega el Company al realm. Esto copia los objetos Company y Employee al realm.
Los objetos Employee relacionados tienen su propio ciclo de vida, independiente del objeto principal Company. Si se elimina el objeto principal, los objetos relacionados se conservan.
auto config = realm::db_config(); auto realmInstance = realm::db(std::move(config)); auto employee1 = realm::Employee{ ._id = 23456, .firstName = "Pam", .lastName = "Beesly"}; auto employee2 = realm::Employee{ ._id = 34567, .firstName = "Jim", .lastName = "Halpert"}; auto company = realm::Company{._id = 45678, .name = "Dunder Mifflin"}; // Use the `push_back` member function available to the // `ListObjectPersistable<T>` template to append `Employee` objects to // the `Company` `employees` list property. company.employees.push_back(&employee1); company.employees.push_back(&employee2); realmInstance.write([&] { realmInstance.add(std::move(company)); });
Opcionalmente, puede crear una relación inversa para hacer referencia al objeto principal desde el objeto relacionado. Para obtener más información, consulte: Crear un objeto con una relación inversa.
Modelo
Para obtener más información sobre cómo modelar una relación de muchos a muchos, consulte: Definir una relación de muchos a muchos.
namespace realm { struct Employee { realm::primary_key<int64_t> _id; std::string firstName; std::string lastName; // You can use this property as you would any other member // Omitting it from the schema means the SDK ignores it std::string jobTitle_notPersisted; }; // The REALM_SCHEMA omits the `jobTitle_notPersisted` property // The SDK does not store and cannot retrieve a value for this property REALM_SCHEMA(Employee, _id, firstName, lastName) } // namespace realm
struct Company { int64_t _id; std::string name; // To-many relationships are a list, represented here as a // vector container whose value type is the SDK object // type that the list field links to. std::vector<Employee*> employees; }; REALM_SCHEMA(Company, _id, name, employees)
Crear un objeto con una relación inversa
Para crear un objeto con una relación inversa con otro, asigne el puntero del objeto relacionado a la propiedad de relación del objeto principal. Mueva el objeto al dominio usando la función Realm.add() dentro de una transacción de escritura.
En este ejemplo, creamos dos objetos Person, cada uno con una relación de uno a uno con el mismo objeto Dog. El Dog tiene una relación inversa con cada objeto Person. El vínculo de retroceso de la relación inversa se actualiza automáticamente cuando un objeto Person vinculado actualiza su relación Dog.
auto config = realm::db_config(); auto realm = realm::db(std::move(config)); auto dog = realm::Dog{.name = "Bowser"}; auto [jack, jill] = realm.write([&realm]() { auto person = realm::Person{.name = "Jack", .age = 27, .dog = nullptr}; realm::Person person2; person2.name = "Jill"; person2.age = 28; person2.dog = nullptr; return realm.insert(std::move(person), std::move(person2)); }); realm.write([&dog, jack = &jack]() { jack->dog = &dog; }); // After assigning `&dog` to jack's `dog` property, // the backlink automatically updates to reflect // the inverse relationship through the dog's `owners` // property CHECK(jack.dog->owners.size() == 1); realm.write([&dog, jill = &jill]() { jill->dog = &dog; }); // After assigning the same `&dog` to jill's `dog` // property, the backlink automatically updates CHECK(jill.dog->owners.size() == 2); CHECK(jack.dog->owners.size() == 2); // Removing the relationship from the parent object // automatically updates the inverse relationship realm.write([jack = &jack]() { jack->dog = nullptr; }); CHECK(jack.dog == nullptr); CHECK(jill.dog->owners.size() == 1);
Modelo
Para obtener más información sobre cómo modelar una relación inversa, consulte: Definir una relación inversa.
struct Dog; struct Person { realm::primary_key<int64_t> _id; std::string name; int64_t age = 0; Dog* dog; }; REALM_SCHEMA(Person, _id, name, age, dog) struct Dog { realm::primary_key<int64_t> _id; std::string name; int64_t age = 0; linking_objects<&Person::dog> owners; }; REALM_SCHEMA(Dog, _id, name, age, owners)
Crear un objeto con una propiedad de mapa
Cuando crea un objeto que tiene una propiedad de mapa, puede establecer los valores de las claves de varias maneras:
Establece claves y valores en el objeto y luego agrega el objeto al realm
Establezca las claves y los valores del objeto directamente dentro de una transacción de escritura
auto config = realm::db_config(); auto realm = realm::db(std::move(config)); auto employee = realm::Employee{ ._id = 8675309, .firstName = "Tommy", .lastName = "Tutone"}; employee.locationByDay = { {"Monday", realm::Employee::WorkLocation::HOME}, {"Tuesday", realm::Employee::WorkLocation::OFFICE}, {"Wednesday", realm::Employee::WorkLocation::HOME}, {"Thursday", realm::Employee::WorkLocation::OFFICE}}; realm.write([&] { realm.add(std::move(employee)); employee.locationByDay["Friday"] = realm::Employee::WorkLocation::HOME; });
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 auto mapKey = "Monday.Morning"; auto encodedMapKey = "Monday%2EMorning";
Modelo
Para obtener más información sobre los tipos de datos de mapas admitidos, consulte: Mapa/Diccionario.
namespace realm { struct Employee { enum class WorkLocation { HOME, OFFICE }; int64_t _id; std::string firstName; std::string lastName; std::map<std::string, WorkLocation> locationByDay; }; REALM_SCHEMA(Employee, _id, firstName, lastName, locationByDay) } // namespace realm
Crear un objeto con una propiedad establecida
Puedes crear objetos que contengan propiedades de conjunto como cualquier objeto de Realm, pero solo puedes mutar una propiedad de conjunto dentro de una transacción de escritura. Esto significa que solo puedes establecer los valores de una propiedad de conjunto dentro de una transacción de escritura.
auto realm = realm::db(std::move(config)); // Create an object that has a set property auto docsRealmRepo = realm::Repository{.ownerAndName = "mongodb/docs-realm"}; // Add the object to the database and get the managed object auto managedDocsRealm = realm.write([&]() { return realm.add(std::move(docsRealmRepo)); }); // Insert items into the set auto openPullRequestNumbers = {3059, 3062, 3064}; realm.write([&] { for (auto number : openPullRequestNumbers) { // You can only mutate the set in a write transaction. // This means you can't set values at initialization, // but must do it during a write. managedDocsRealm.openPullRequestNumbers.insert(number); } });
Modelo
Para obtener más información sobre los tipos de datos de conjunto admitidos, consulte: Conjunto.
namespace realm { struct Repository { std::string ownerAndName; std::set<int64_t> openPullRequestNumbers; }; REALM_SCHEMA(Repository, ownerAndName, openPullRequestNumbers) } // namespace realm
Crear un objeto asimétrico
Puede crear un objeto asimétrico que se sincronice unidireccionalmente mediante la ingesta de datos con la base de datos de Atlas vinculada a su aplicación Atlas App Services. No puede acceder a un objeto asimétrico localmente, eliminarlo de un dominio ni consultarlo.
auto weatherSensorReading = realm::WeatherSensorReading{.deviceId = "WX1278UIT", .temperatureInFahrenheit = 64.7, .windSpeedInMph = 7}; realm.write([&] { realm.add(std::move(weatherSensorReading)); });
Para obtener más información sobre cómo trabajar con objetos asimétricos, consulte Stream Data to Atlas - C++ SDK.
Modelo
Para obtener más información sobre cómo definir un objeto asimétrico, consulte: Definir un objeto asimétrico.
struct WeatherSensorReading { realm::primary_key<realm::object_id> _id{realm::object_id::generate()}; std::string deviceId; double temperatureInFahrenheit; int64_t windSpeedInMph; }; REALM_ASYMMETRIC_SCHEMA(WeatherSensorReading, _id, deviceId, temperatureInFahrenheit, windSpeedInMph)