Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

CRUD - 创建 - C++ SDK

在此页面上

  • 写事务(write transaction)
  • 创建新对象
  • 创建对象
  • 创建嵌入式对象
  • 创建具有对一关系的对象
  • 创建具有对多关系的对象
  • 创建具有反向关系的对象
  • 创建具有映射属性的对象
  • 创建具有已设置属性的对象
  • 创建非对称对象

Realm使用高效的storage engine来持久化对象。 您可以在 Realm 中创建对象、更新Realm 中的对象,以及最终从 Realm 中删除对象。 由于这些操作会修改 Realm 的状态,因此我们将其称为写入。

Realm 通过事务来处理写入。 事务是一系列读写操作,Realm 将其视为单个不可分割的操作。 换言之,事务是“全有或全无”:事务中的所有操作要么成功,要么事务中的所有操作都不生效。

所有写入都必须在事务中进行。

Realm 一次只允许一个打开的事务。 Realm 会阻止其他线程上的其他写入,直到打开的事务完成。 因此,在事务中从 Realm 读取值时,不存在争用情况。

完成事务后,Realm 要么提交事务,要么取消事务:

  • 当 Realm提交事务时,Realm 会将所有更改写入磁盘。 对于同步 Realm,SDK 会将更改排队以便与 Atlas Device Sync 进行同步。

  • 当 Realm取消写事务或事务中的操作导致错误时,所有更改都将被丢弃(或“回滚”)。

要创建对象,必须使用 realm命名空间对其进行实例化。 在写事务(write transaction)中使用 Realm .add() 函数将对象移动到域中。

当您将对象移入 Realm 时,会将对象作为右值使用。 您必须使用托管对象进行任何数据访问或观察。 在此示例中,将dog对象复制到 Realm 时会将其作为右值使用。 您可以返回托管对象以继续使用它。

// 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)); });

有关对象建模的更多信息,请参阅:定义新的 Realm 对象类型。

namespace realm {
struct Dog {
std::string name;
int64_t age;
};
REALM_SCHEMA(Dog, name, age)
} // namespace realm

要创建嵌入式对象,请将嵌入式对象的原始指针分配给父对象的属性。 在写事务中使用Realm.add() 函数将父对象移动到 Realm 中。

在此示例中,我们将嵌入式对象的原始指针ContactDetails *分配给父对象Business.contactDetails的嵌入式对象属性。

然后,我们将business对象添加到 Realm 中。 这会将businesscontactDetails对象复制到 Realm。

由于ContactDetails是嵌入式对象,因此它没有独立于主Business对象的生命周期。 如果删除Business对象,也会删除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)); });

有关嵌入式对象建模的更多信息,请参阅:定义嵌入式对象。

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

要创建与另一个对象具有对一关系的对象,请将相关对象的原始指针分配给主对象的关系属性。 在写事务中使用Realm.add() 函数将对象移动到 Realm 中。

在此示例中,我们将相关对象的原始指针FavoriteToy *分配给主对象的关系属性Dog.favoriteToy 。 然后,当我们将dog对象添加到 Realm 时,会将dogfavoriteToy复制到 Realm。

相关的favoriteToy对象具有自己的生命周期,独立于主dog对象。 如果删除主对象,则相关对象将保留。

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)); });

您可以选择创建反向关系,以便从相关对象。 有关更多信息,请参阅:创建具有反向关系的对象。

有关对一对一关系进行建模的更多信息,请参阅:定义对一关系。

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)

要创建与一个或多个对象具有对多关系的对象,请执行以下操作:

  • 初始化主对象和相关对象

  • 使用 Realm 对象列表可用的push_back成员函数将相关对象的原始指针附加到主对象的列表属性

  • 在写事务中使用Realm.add() 函数将对象移动到 Realm 中。

在此示例中,我们将相关对象的原始指针 - Employee * - 附加到主对象的关系属性 - Company.employees 。 这将创建从Company对象到Employee对象的单向连接。

然后,将Company添加到 Realm。 这会将CompanyEmployee对象复制到 Realm。

相关的Employee对象具有自己的生命周期,独立于主Company对象。 如果删除主对象,相关对象将保留。

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)); });

您可以选择创建反向关系,以便从相关对象。 有关更多信息,请参阅:创建具有反向关系的对象。

有关建模对多关系的更多信息,请参阅:定义对多关系。

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)

要创建与另一个对象具有反向关系的对象,请将相关对象的原始指针分配给主对象的关系属性。 在写事务中使用Realm.add() 函数将对象移动到 Realm 中。

在此示例中,我们创建了两个Person对象,每个对象都与同一Dog对象存在一对一关系。 Dog与每个Person对象都有反向关系。 当链接的Person对象更新其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);

有关对反向关系进行建模的更多信息,请参阅:定义反向关系。

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)

创建具有映射属性的对象时,可以通过以下几种方法来设置键的值:

  • 在对象上设置键和值,然后将对象添加到 Realm

  • 直接在写事务中设置对象的键和值

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 不允许在映射键中使用 .$ 字符。您可以使用百分比编码和解码来存储包含这些不允许的任一字符的映射键。

// Percent encode . or $ characters to use them in map keys
auto mapKey = "Monday.Morning";
auto encodedMapKey = "Monday%2EMorning";

有关支持的地图数据类型的更多信息,请参阅:地图/字典。

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

您可以像创建任何 Realm 对象一样创建包含设置属性的对象,但只能在写事务中更改设置属性。 这意味着您只能在写事务中设置已设置属性的值。

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);
}
});

有关支持的集合数据类型的更多信息,请参阅:集合。

namespace realm {
struct Repository {
std::string ownerAndName;
std::set<int64_t> openPullRequestNumbers;
};
REALM_SCHEMA(Repository, ownerAndName, openPullRequestNumbers)
} // namespace realm

您可以创建一个非对称对象,通过数据导入单向同步到链接到Atlas App Services App 的Atlas数据库。 您无法在本地访问权限非对称对象,无法将其从域中删除,也无法对其进行查询。

auto weatherSensorReading =
realm::WeatherSensorReading{.deviceId = "WX1278UIT",
.temperatureInFahrenheit = 64.7,
.windSpeedInMph = 7};
realm.write([&] { realm.add(std::move(weatherSensorReading)); });

有关使用不对称对象的更多信息,请参阅将数据流式传输到 Atlas - C++ SDK。

有关定义非对称对象的更多信息,请参阅:定义非对称对象。

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)

后退

CRUD — C++ SDK