Project

General

Profile

[Wt::Dbo] how can I implement a cache for objects ?

Added by Rodolphe Basset about 10 years ago

I'd like to preload my database and check if an object is already in the collection before querying or adding it.

something like that :

class C {
public:
C::C(std::string strName) : _name(strName) {}
C::~C() {}

    template<class Action>
    void persist(Action& a) {
        dbo::field(a, _name, "name");
    }

private:
    std::string _name;
};

C * newC = new C("First");
session.add(newC);
dbo::collection<dbo::ptr<C> > listC = session.find<C>();

how can I check that newC is already in listC ?

implement C::operator ==() ? and parse dbo::collection ?

can I find directly form a dbo::ptr in session cache ?


Replies (6)

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Cameron Angus about 10 years ago

It's not clear to me exactly what you're asking. Do you want to check if an object already exists in the database table? Or you want to implement a local cache and you're asking how can you check if it's already in the cache?

Assuming the latter, well you obviously need to define what you mean by an object already being there. If you were to define it as "an object is already there if there is an object with the same name", then I guess the most straightforward way would be:

1. Query the database for all records and store in listC (as in your code)

  1. Iterate over listC and store in a map (std::map< std::string, dbo::ptr< C > > mapC; for(auto c: listC) { mapC[c->getName()] = c; }
  2. Then to check if an object is in your cache, just use mapC.find(a_name) != mapC.end()

Whether or not this would be good Dbo practice though I'm not sure. Internally Dbo is already caching objects. Also, if you are trying to enforce uniqueness of objects on a given field, then you should probably just make that field the primary key of your table.

Cameron.

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Rodolphe Basset about 10 years ago

The first goal is to avoid SQL Query and binding of parameters, to separate DB layer from Business Object layer.

Primary keys are already set, so should I query with

session.load(pObject->id());

to check if object is loaded ?

Will a map.find() be faster or not ?

thanks,

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Koen Deforche about 10 years ago

Hey,

session.load(pObject->id());

This will effectively first search an internal map to see if this object is already in memory (which means there is already a ptr to it), so a map.find() will not be faster by itself. To populate the 'cache' you thus only need to keep ptr's to objects around.

Regards,

koen

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Rodolphe Basset about 10 years ago

OK, got it.

I understand that internal Wt::Dbo cache map is keyed on id ?

That will not work with sequence ids that are known only after adding object to the database.

So, I need to have natural ids, to check if new Object is already existing, with unique name attribute as for an example, or with composite natural primary key if needed.

Thanks.

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Koen Deforche about 10 years ago

Hey,

Yes, it's keyed on id.

I'm not sure what you have in mind for use-case, but to get the idea for a newly added object, you can do:

session.add(ptr);
ptr.flush();
std::cerr << "Id: " << ptr.id() << std::endl;

Regards,

koen

RE: [Wt::Dbo] how can I implement a cache for objects ? - Added by Rodolphe Basset about 10 years ago

That's OK.

I load CSV files with natural data only (no id).

I have to check if data already exists in DB / cache.

If it exists, I don't insert it.

(that's why my code used to crash before, with contraint failed exception on inserting existing objects)

If I have an object with natural primary key = "name", I can check with the matching "name" column of my CSV file if object is already in Dbo session cache.

Thanks,

    (1-6/6)