[odb-users] Recursive Loading Issue with Mutual Aggregation in ODB
Classes
xuewen wang
xuewen.ok at gmail.com
Fri Aug 2 11:21:03 EDT 2024
Dear ODB Development Team,
I am writing to report a potential issue with the ODB ORM system when two
model classes include or aggregate each other. This mutual aggregation can
lead to recursive loading problems when querying records from the database.
### Example Scenario
Consider the following two classes, `Person` and `Address`, where each
`Person` has an `Address` and each `Address` has a `Person`.
#### Person.hxx
cpp
#pragma once
#include <memory>
#include <odb/core.hxx>
#include "Address.hxx"
#pragma db object
class Person
{
public:
Person() = default;
Person(const std::string& name, std::shared_ptr<Address> address)
: name_(name), address_(address) {}
const std::string& name() const { return name_; }
std::shared_ptr<Address> address() const { return address_; }
private:
friend class odb::access;
#pragma db id auto
unsigned long id_;
std::string name_;
#pragma db not_null
std::shared_ptr<Address> address_;
};
#### Address.hxx
cpp
#pragma once
#include <memory>
#include <odb/core.hxx>
#include "Person.hxx"
#pragma db object
class Address
{
public:
Address() = default;
Address(const std::string& street, std::shared_ptr<Person> person)
: street_(street), person_(person) {}
const std::string& street() const { return street_; }
std::shared_ptr<Person> person() const { return person_; }
private:
friend class odb::access;
#pragma db id auto
unsigned long id_;
std::string street_;
#pragma db not_null
std::shared_ptr<Person> person_;
};
### Issue
When querying a `Person` from the database, ODB will try to load the
associated `Address`. While loading the `Address`, ODB will again try to
load the associated `Person`, leading to a recursive loop.
### Query Example
cpp
#include <odb/database.hxx>
#include <odb/transaction.hxx>
#include <odb/sqlite/database.hxx>
#include "Person.hxx"
#include "Person-odb.hxx"
#include "Address.hxx"
#include "Address-odb.hxx"
int main()
{
std::shared_ptr<odb::database> db(new odb::sqlite::database("test.db",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
// Start a transaction
odb::transaction t(db->begin());
// Query a person by id
std::shared_ptr<Person> person(db->load<Person>(1));
// Commit the transaction
t.commit();
// Access the person's address
std::shared_ptr<Address> address = person->address();
return 0;
}
In this example, loading a `Person` will recursively load the `Address`,
which will again try to load the `Person`, causing a recursive call.
### Request
Could you please look into this issue and provide a resolution or
workaround?
Thank you for your attention to this matter.
Best regards,
More information about the odb-users
mailing list